home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
SHDK_2
/
SKYHAWK.DOC
< prev
next >
Wrap
Text File
|
1992-06-15
|
179KB
|
6,972 lines
THE SKYHAWK DEVELOPMENT LIBRARY
by
Bill Madison
W. G. Madison and Associates, Ltd.
13819 Shavano Downs
P.O. Box 780956
San Antonio, TX 78278-0956
(512)492-2777
CIS 73240,342
Copyright 1992 Madison & Associates
All Rights Reserved
TERMS AND CONDITIONS
This collection of units with the associated TEST*.*
files and this .DOC file may be freely used, copied,
and distributed for non-commercial use, provided only
that no fee is charged for the package beyond a nominal
copying charge, and provided that the entire package is
distributed IN UNALTERED FORM. The sole exception to
this latter restriction is that bona-fide computer
clubs and user groups may append text material to the
documentation file, provided that any material so
appended is clearly identified as to its source, its
beginning, and its end.
While no registration or other fee is charged for the
non-commercial use of the collection, we will willingly
accept contributions from those wishing to support our
work. An amount of $10.00 is suggested. Checks should
be made out to W. G. Madison and Associates, Ltd., and
forwarded to the above address.
Those wishing to use the SkyHawk collection for commer-
cial purposes should contact Madison & Associates at
the above address to arrange terms.
i
PREFACE
The Cessna SkyHawk is a small single engine airplane. It is
also the airplane in which I learned to fly. On the day of my
first solo flight, I felt as the poet must have when he wrote:
Up, up the long delirious burning blue,
I've topped the wind-swept heights with easy grace,
Where never lark or even eagle flew
And while with silent uplifting mind I've trod
The high, untrespassed sanctity of space,
Put out my hand and touched the face of God!
John Gillespie Magee, Jr.
"High Flight"
As the SkyHawk Development Library was being written and
began to be used at Madison and Associates, we found that we felt
somewhat the same sense of freedom and mastery of the environment
when using the library as that which I had felt during my first
solo. We sincerely hope that you will share these feelings with
us.
ii
INTRODUCTION
The SkyHawk Development Library is a collection of units
compilable under Borland's Turbo PASCAL 5 and above. Some of the
functionalities are to be found in other collections but are re-
implemented here in an extended form or to provide a different
approach. Some are unique to the SkyHawk collection. All are pro-
vided with the goal of removing the necessity of "reinventing the
wheel" during the development process.
The collection is dynamic, in the sense that it is being
constantly augmented by the addition of new units and the im-
provement of the existing ones. We welcome all suggestions for
additional units and/or routines, bug reports, and general com-
ments. Just drop us a note at the address above. Or call us
(9:00am - 5:00pm Central time) or drop us an EMAIL message on
CompuServe using the CIS address shown.
The SkyHawk collection depends on the TurboProfessional 5.0
library from TurboPower Software. Most of the units were initial-
ly developed while we were working on a series of projects for
which conversion to an object oriented design was not economical-
ly feasible. Thus the dependence on TurboProfessional rather than
ObjectProfessional. In most cases, however, you will find that
conversion to object oriented code will be trivial. When time
permits, Madison & Associates intends to convert the entire
collection to objects and to provide both.
iii
WHAT'S IN THE LIBRARY?
____________________________
SHCLRDEF
ShClrDef is a unit which is serves two functions;
* It defines constants such that each normally allowable
combination of text forground and background colors can be
specified by name; e.g., YellowOnBlack, MagentaOnLtGray.
* It interfaces a function which displays a "screen selec-
tion panel", allowing the user to move a special cursor to
a desired forground/background color combination and then
select that combination by pressing <Ret>, returning the
attribute value. This function is particularly useful in
the construction of installation programs. The end user
can be permitted to select color combinations for any par-
ticular screen element, which can then be displayed.
Additionally, a function is interfaced which, given an
attribute value as input, returns a string containing the
attribute name; e.g.,
ColorName($1E)
returns 'YellowOnBlue'.
____________________________
SHCMDLIN
Developers of command line driven programs constantly face
the problem of providing acceptable levels of syntax flexibility
on the command line coupled with a minimum level of labor in
coding the command line analyzer. This unit, ShCmdLin, removes
all of the heartburn associated with the coding, while providing
a maximum level of syntactic flexibility to the user.
iv
____________________________
SHCMPLX
ShCmplx is a complex arithmetic unit. It provides for the
basic binary arithmetic functions (addition, subtraction, multi-
plication, division), plus the raising of a complex number to a
real power. Conversion functions are provided to convert between
a complex number represented in Cartesian form and one repre-
sented in polar form. Finally, provision is made to convert a
complex number in Cartesian form to a string; or a complex in
polar form to a string expressing the angle either in degrees or
in radians.
____________________________
SHCRCCHK
When the DOS COPY command is used, no true read-after-write
verification is performed. The only way to assure that the re-
cording was correct is to read the file after writing, and com-
pare the output file, byte for byte, with the input. For very
long files this can result in unacceptable delays.
A reasonable compromise between speed and reliability is to
calculate the cyclic redundancy check (CRC) word of the input
file as it is being copied, and then on completion of the copying
operation, read back the output file and calculate its CRC. If
the two compare and the files are of the same size, the probabil-
ity that the two files differ is extremely small.
ShCrcChk is a unit which interfaces two functions, both of
which calculate the CRC16 of a file whose name is provided as a
string parameter. One of the functions simply calculates the CRC
and returns it; the other in addition copies the input file to
another file whose name is provided as a second string parameter.
____________________________
SHERRMSG
ShErrMsg is a unit which installs an exit procedure in Turbo
PASCAL programs. This exit procedure displays a short explanatory
message whenever a program terminates abnormally; whenever it re-
turns to DOS with a return code other than zero.
It also interfaces replacements for the HALT and RUNERROR
procedures in Turbo PASCAL's SYSTEM unit. These procedures per-
form functions not provided by PASCAL's normal termination
procedures.
v
____________________________
SHFINANC
ShFinanc is a higher level unit than most of the others in
this package. Its inclusion in this package is justified, how-
ever, by the need which we have frequently encountered to include
compound interest and annuity calculations in various systems
which we have implemented.
The functions include compound present value and amount, and
annuity present value and amount for both ordinary annuities and
annuities due. Also included are functions returning the number
of payments given the interest rate and annuity present value as
well as a function returning the interest rate of an annuity
given the number of payments and present value.
____________________________
SHLIST
Lists, rings, and stacks are among the most common data
structures used (after arrays). They are also probably among the
worst offenders when it comes to "re-inventing the wheel." Many
programmers build special purpose list manipulation routines each
time a list is needed. Obviously, a generic list manipulation
package is a valuable addition to the available "bag of tricks."
ShList contains all of the routines necessary to establish
and manipulate singly and doubly linked lists, rings, and stacks.
The data associated with any given list, ring, or stack can be
any standard or user defined data type. The structure of the data
can change, but the total length of the data must remain con-
stant. Thus, for example, variant records can be used.
____________________________
SHLNGSTR
ShLngStr is a unit which provides the ability to manipulate
long strings (up to 65517 characters in length) using Turbo
PASCAL.
ShLngStr stores all of its string data on the heap. When a
variable is declared to be of type LongString, this declaration
establishes only a pointer in the data segment. The LongString
must then be initialized prior to use. This initialization estab-
lishes a maximum allowable string length, which may now vary from
one LongString to the next. Only the amount of heap space requir-
ed for the initialized maximum length is used. In this respect,
the analog of a string declaration of, for example, "var
string[127];" has been preserved. Any of the procedures and
functions in this unit will observe the "declared" maximum
length, and will adjust their behavior appropriately.
vi
____________________________
SHUTILPK
ShUtilPk is a collection of miscellaneous utility proce-
dures, generally lower level than those in the other units of
this collection.
vii
UNIT DEPENDENCIES
As mentioned above, the SkyHawk collection is dependent upon
the TurboProfessional-5.0 library published by TurboPower Soft-
ware. There are also dependencies within the SkyHawk collection
itself. The following matrix shows these dependencies.
D S S S T T T T T T T
O H H H P P P P P P P
S E L U 8 C D I M S W
| R I T 0 R O N E T I
+--uses--> | R S I 8 T S L M R N
| | M T L 7 | | I C I D
| | S | P | | | N H N O
| | G | K | | | E K G W
| | | | | | | | | | | |
ShClrDef - - - - - X - - - - X
ShCmdLin X - X X - - - - - - -
ShCmplx - - - - - - - - - - -
ShCrcChk X - - - - - - - - - -
ShDatPk X - - - - - - - - - -
ShErrMsg - - - - - - - - - - -
ShFinanc - X - X X X - - - X -
ShList - - - - - - - X X X -
ShLngStr - - - - - - - X X X -
ShUtilPk - - - - - - X - - X -
Unit Dependencies Matrix
viii
06/15/92 09:46am
ShClrDef
A Color Definition Unit
INTRODUCTION
ShClrDef is a unit which serves two functions;
* It defines constants such that each normally allowable
combination of text forground and background colors can be
specified by name; e.g., YellowOnBlack, MagentaOnLtGray.
* It interfaces a function which displays a "screen selec-
tion panel", allowing the user to move a special cursor to
a desired forground/background color combination and then
select that combination by pressing <Ret>. The attribute
value is returned.
Additionally, a function is interfaced which, given an
attribute value as input, returns a string containing the
attribute name; e.g.,
ColorName($1E)
returns 'YellowOnBlue'.
INTERFACED ELEMENTS
Constants
=========
{Black text} {Blue text}
BlackOnBlack = $00; BlueOnBlack = $01;
BlackOnBlue = $10; BlueOnBlue = $11;
BlackOnGreen = $20; BlueOnGreen = $21;
BlackOnCyan = $30; BlueOnCyan = $31;
BlackOnRed = $40; BlueOnRed = $41;
BlackOnMagenta = $50; BlueOnMagenta = $51;
BlackOnBrown = $60; BlueOnBrown = $61;
BlackOnLtGray = $70; BlueOnLtGray = $71;
ShClrDef 1-1
{Green text} {Cyan text}
GreenOnBlack = $02; CyanOnBlack = $03;
GreenOnBlue = $12; CyanOnBlue = $13;
GreenOnGreen = $22; CyanOnGreen = $23;
GreenOnCyan = $32; CyanOnCyan = $33;
GreenOnRed = $42; CyanOnRed = $43;
GreenOnMagenta = $52; CyanOnMagenta = $53;
GreenOnBrown = $62; CyanOnBrown = $63;
GreenOnLtGray = $72; CyanOnLtGray = $73;
{Red text} {Magenta text}
RedOnBlack = $04; MagentaOnBlack = $05;
RedOnBlue = $14; MagentaOnBlue = $15;
RedOnGreen = $24; MagentaOnGreen = $25;
RedOnCyan = $34; MagentaOnCyan = $35;
RedOnRed = $44; MagentaOnRed = $45;
RedOnMagenta = $54; MagentaOnMagenta = $55;
RedOnBrown = $64; MagentaOnBrown = $65;
RedOnLtGray = $74; MagentaOnLtGray = $75;
{Brown text} {Light Gray text}
BrownOnBlack = $06; LtGrayOnBlack = $07;
BrownOnBlue = $16; LtGrayOnBlue = $17;
BrownOnGreen = $26; LtGrayOnGreen = $27;
BrownOnCyan = $36; LtGrayOnCyan = $37;
BrownOnRed = $46; LtGrayOnRed = $47;
BrownOnMagenta = $56; LtGrayOnMagenta = $57;
BrownOnBrown = $66; LtGrayOnBrown = $67;
BrownOnLtGray = $76; LtGrayOnLtGray = $77;
{Dark Gray text} {Light Blue text}
DkGrayOnBlack = $08; LtBlueOnBlack = $09;
DkGrayOnBlue = $18; LtBlueOnBlue = $19;
DkGrayOnGreen = $28; LtBlueOnGreen = $29;
DkGrayOnCyan = $38; LtBlueOnCyan = $39;
DkGrayOnRed = $48; LtBlueOnRed = $49;
DkGrayOnMagenta = $58; LtBlueOnMagenta = $59;
DkGrayOnBrown = $68; LtBlueOnBrown = $69;
DkGrayOnLtGray = $78; LtBlueOnLtGray = $79;
{Light Green Text} {Light Cyan text}
LtGreenOnBlack = $0A; LtCyanOnBlack = $0B;
LtGreenOnBlue = $1A; LtCyanOnBlue = $1B;
LtGreenOnGreen = $2A; LtCyanOnGreen = $2B;
LtGreenOnCyan = $3A; LtCyanOnCyan = $3B;
LtGreenOnRed = $4A; LtCyanOnRed = $4B;
LtGreenOnMagenta = $5A; LtCyanOnMagenta = $5B;
LtGreenOnBrown = $6A; LtCyanOnBrown = $6B;
LtGreenOnLtGray = $7A; LtCyanOnLtGray = $7B;
ShClrDef 1-2
{Light Red text} {Light Magenta text}
LtRedOnBlack = $0C; LtMagentaOnBlack = $0D;
LtRedOnBlue = $1C; LtMagentaOnBlue = $1D;
LtRedOnGreen = $2C; LtMagentaOnGreen = $2D;
LtRedOnCyan = $3C; LtMagentaOnCyan = $3D;
LtRedOnRed = $4C; LtMagentaOnRed = $4D;
LtRedOnMagenta = $5C; LtMagentaOnMagenta = $5D;
LtRedOnBrown = $6C; LtMagentaOnBrown = $6D;
LtRedOnLtGray = $7C; LtMagentaOnLtGray = $7D;
{Yellow text} {White text}
YellowOnBlack = $0E; WhiteOnBlack = $0F;
YellowOnBlue = $1E; WhiteOnBlue = $1F;
YellowOnGreen = $2E; WhiteOnGreen = $2F;
YellowOnCyan = $3E; WhiteOnCyan = $3F;
YellowOnRed = $4E; WhiteOnRed = $4F;
YellowOnMagenta = $5E; WhiteOnMagenta = $5F;
YellowOnBrown = $6E; WhiteOnBrown = $6F;
YellowOnLtGray = $7E; WhiteOnLtGray = $7F;
Types
=====
Orientation = (Vertical, Horizontal);
Determines whether the color selection panel displayed by
SelectColors is presented with its long dimension oriented
vertically or horizontally on the screen.
Routines
========
____________________________
SELECTCOLORS
Declaration:
function SelectColors(Row, Col, BegAttr : byte;
CpFrameChars : FrameArray;
Orient : Orientation;
ErasePanelOnExit,
EraseCursorOnExit,
WrapCursor : boolean;
Header : string) : byte;
Purpose:
Displays a color selection panel, permitting the user to
move a special cursor using the arrow keys and select a desired
color combination using the <CR> key.
ShClrDef 1-3
Comments:
The user navigates the panel with the arrow keys and selects
the desired color combination by pressing <CR>. The attribute
byte value currently under the cursor will be returned. The user
can also press <INS>, which will return a function value of $FF,
and by convention, should be taken to indicate that the currently
selected attribute value is to be unchanged. Additionally, the
user can press <ESC>, returning a function value of $FE, which by
convention should be taken to indicate that the current color
selection run is completed. Finally, a return of $FD indicates
that the user has pressed the <F1> key either alone or in
combination with one of the shift-type keys (<L-SHIFT>, <R-
SHIFT>, <CTRL>, or <ALT>), and by convention indicates that the
user is requesting help.
The function performs the following actions:
* Displays a 16x8 panel of text colors with the window
coordinates of the upper left corner at coordinates X=Col,
Y=Row.
* The attribute at which the cursor will be initially placed
is at BegAttr.
* The color panel will be framed using the characters
specified in CpFrameChars.
* The orientation of the long dimension of the selection
panel is determined as specified by Orient.
* ErasePanelOnExit determines whether the panel is erased or
preserved on the screen when SelectColors returns to the
caller. The panel is always disposed, and its heap space
reclaimed.
* EraseCursorOnExit is only effective if ErasePanelOnExit is
false. If the panel is to be preserved between calls to
SelectColors, EraseCursor determines whether the or not
the cursor will continue to be displayed along with the
panel.
* WrapCursor determines whether the cursor will wrap both
horizontally and vertically. True allows the cursor to
wrap; False inhibits further cursor movement when a window
edge is reached.
* Header is the header line which will be displayed on the
panel. It can be supplied as an empty string (''), in
which case no header will be displayed.
ShClrDef 1-4
* The function returns a normal text attribute byte, with
the following exceptions:
Return Explanation
------ -----------
$FF <INS> was pressed by the user. Leave the
current value unchanged.
$FE <ESC> was pressed by the user. Accept all
current values and consider the run
completed.
$FD <F1> was pressed by the user. Provide a
HELP screen or message.
$F0 Error in MakeWindow
$F1 Error in DisplayWindow
____________________________
COLORNAME
Declaration:
function ColorName(Attr : byte) : string;
Purpose:
Given a text attribute byte, ColorName returns the attribute
color name as defined above; e.g., ColorName($1E) will return
'YellowOnBlue'.
Comment:
If a byte value is passed which does not correspond to a
valid text attribute, an empty string is returned.
Example:
The statement
WriteLn(ColorName($73));
displays the string
CyanOnLtGray
on the screen.
ShClrDef 1-5
06/15/92 09:46am
This page has been deliberately left
blank, except for this message.
ShClrDef 1-6
ShCmdLin
A Command Line Parsing Unit
INTRODUCTION
Developers of command line driven programs constantly face
the problem of providing acceptable levels of syntax flexibility
on the command line coupled with a minimum level of labor in
coding the command line analyzer. This unit, ShCmdLin, removes
all of the heartburn associated with the coding, while providing
a maximum level of syntactic flexibility to the user.
ShCmdLin contains all those routines necessary not only to
parse the command line but also to determine the current DOS
switch lead-in character and, if desired, change it. Further, the
parsing routine allows a set of characters (rather than just a
single character) to be defined as acceptable for switch lead-in.
It further permits a set of characters to serve as the switch
value lead-in. Thus, for example, one could use ['/','-'] for
switch lead-in, and [':','='] for value lead-in. This would have
the effect of making the following two command tails functionally
identical:
/Alpha-Bravo=27.9-Charlie:14/Delta=Echo
-Alpha/Bravo:27.9/Charlie=14-Delta:Echo
For each switch, the parsing routine prepares one variant
record (see below, the definition of the SwRec type) and appends
it to a list, from which it may be retrieved as required. Apply-
ing this to the example above, the following will be true.
In each case in the example, the NAME of the first switch is
Alpha, and it has no assigned value (switches lacking an assigned
value will be returned as a string-type, but with an empty string
as the value); the NAME of the second switch is Bravo and it has
a real-type value of 27.9; the NAME of the third is Charlie and
it has an integer-type value of 14; and the NAME of the fourth is
Delta and it has a string-type value of 'Echo'.
ShCmdLin 2-1
!!CAUTIONARY NOTE!!
The characters ^C (<ETX> or #3), ^M (<CR> or #13), and
^[ (<ESC> or #27) cannot be embedded in a command tail.
The parser, however, can be used to parse arbitrary
strings; not just command tails. THESE ARBITRARY
STRINGS MUST NOT CONTAIN ANY OF THE THREE INDICATED
CHARACTERS. These characters are RESERVED for internal
use by the parser.
!!END OF CAUTIONARY NOTE!!
!!CAUTIONARY NOTE!!
MARK/RELEASE must not be used for heap management when
using this unit. GETMEM/FREEMEM or NEW/DISPOSE must be
used instead.
!!END OF CAUTIONARY NOTE!!
INTERFACED ELEMENTS
Types
=====
ValueType = (VtStr, VtReal, VtInt);
SwRec = record
Name : string;
case SwVal : ValueType of
VtStr : (StrVal : string);
VtReal: (RealVal: Extended);
VtInt : (IntVal : integer);
end; {SwRec}
CharSet = Set of Char;
If you do not have a math coprocessor and do not want to pay
the space and time overhead required for coprocessor emulation,
you may wish to change the VtReal variant in the definition of
SwRec from type Extended to type Real.
ShCmdLin 2-2
Routines
========
____________________________
CLCLOSE
Declaration:
procedure ClClose;
Purpose:
Closes the internal data structures and frees the space
associated with the command line switch list.
Comments:
If GetSwitch is used to retrieve switch values, ClClose
should be called following retrieval of the last switch. If
PopSwitch is used, ClClose need not be called.
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
ClInit GetSwitch PopSwitch
____________________________
CLINIT
Declaration:
procedure ClInit;
Purpose:
Initializes the internal data structures used to store the
command line switch list.
Comments:
ClInit MUST be called prior to any of the other Cl routines.
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
ClClose
ShCmdLin 2-3
____________________________
CLPARSE
Declaration:
procedure ClParse(StrPtr : Pointer; StrOnly : Boolean;
LeadIn, ValDelim : CharSet; var Err : Integer);
Purpose:
To parse a command tail (or other string of similar form),
producing a list of switch names and associated values which can
then be retrieved using the GetSwitch or PopSwitch functions.
Comments:
Parsing is accomplished by invoking the procedure ClParse
with five parameters:
1. StrPtr of type Pointer is used to point to the string to
be parsed. If StrPtr is NIL, the command tail will be
parsed.
2. StrOnly of type Boolean is used to determine if switch
values of type String are to be forced, regardless of the
form of the value. StrOnly = True forces String values.
3. LeadIn of type CharSet is used to identify the set of
characters used to mark the beginning of a switch. It is
suggested that LeadIn be set to [ ReadSwCh ]. The weakest
condition used should be that the expression ( ReadSwCh in
LeadIn ) be TRUE.
4. ValDelim of type CharSet is used to specify the set of
characters which may be used to separate the switch name
from the switch value.
5. Err of type Integer is used to return error conditions.
Prior to the call to ClParse, a call MUST be made to ClInit.
The procedure prepares a list of records, each record con-
taining the name and value of one command line switch. These
records will require 536 bytes of heap space per switch.
All switches (with the optional exception of the first) are
preceded by one of the members of the set LeadIn.
Switches may take values of type Real (actually, Extended),
LongInt, or String. In each case, the switch value is separated
from the switch name by one of the characters specified in the
parameter ValDelim. Switches which do not take on any explicit
value will be returned as type String, with a value length of
zero.
ShCmdLin 2-4
Assuming StrOnly = FALSE in the call, switches whose VALUE
is intended to be of type String, but with a FORM qualifying as a
numeric, must be enclosed in either single or double quotation
marks. Otherwise, the value will be returned as a Real or
LongInt, as determined by its specific syntax.
Additionally, any blanks included in String values will be
packed out unless the value is included in quotation marks.
Further, if single quote marks are to be included as part of a
string value, then double quotes must be used to define the
value; and vice versa.
Finally, blanks may be freely entered in the command tail to
improve readability (except as noted above).
Error Returns:
The error parameter returns one of three values:
0 --> No error encountered.
1 --> Unbalanced single quotes encountered.
2 --> Unbalanced double quotes encountered.
3 --> Insufficient heap space to store the switch list.
Assuming the error return is 0, the list of switches has
been successfully prepared and is available for retrieval using
GetSwitch or PopSwitch.
If GetSwitch has been used to retrieve the switch values,
ClClose should be called to release the heap space associated
with the list of switches. This is not necessary if PopSwitch has
been used for retrieval (but it won't hurt anything, either).
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
ClInit ClClose GetSwitch PopSwitch
ShCmdLin 2-5
____________________________
GETSWITCH
Declaration:
function GetSwitch(var Y : SwRec) : boolean;
Purpose:
Retrieves the next switch record in the list of switch
records prepared by ClParse. Returns FALSE if no more.
Comments:
The list of switches can, if desired, be treated as a ring
(thus enabling switches to be read more than once). If GetSwitch
is called again after returning a function value of FALSE, read-
ing will recommence at the top of the list.
Use of GetSwitch and PopSwitch should not be combined. If
they are both used on the same pass through the command tail,
orphan blocks (blocks which have no associated pointer, and thus
cannot be accessed or retrieved) will result on the heap.
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
PopSwitch
ShCmdLin 2-6
____________________________
POPSWITCH
Declaration:
function PopSwitch(var Y : SwRec) : boolean;
Purpose:
Retrieves the next switch record in the list of switch
records prepared by ClParse, and frees its heap space. Returns
FALSE if no more.
Comments:
Since PopSwitch frees the heap space associated with each
switch after it has been returned to the caller, it is not
necessary to call ClClose after reaching the end of the switch
list. For the same reason, however, the switch list cannot be
treated as a ring (that is, the switch list cannot be reread
after the end has been reached).
Use of GetSwitch and PopSwitch should not be combined. If
they are both used on the same pass through the command tail,
orphan blocks (blocks which have no associated pointer, and thus
cannot be accessed or retrieved) will result on the heap.
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
GetSwitch
ShCmdLin 2-7
____________________________
READSWCH
Declaration:
function ReadSwCh : char;
Purpose:
Returns the current switch lead-in character.
Comments:
DOS normally recognizes the character '/' as the switch
lead-in. DOS also permits this character to be changed. In par-
ticular, some installations whose personnel are more comfortable
in a UNIX-like environment have changed the switch lead-in to
'-'. The ReadSwCh function permits the programmer to assure that
the character which DOS recognizes will be included in the set of
permissible lead-in characters which the parser will also
recognize.
Examples:
See the files TESTCL.PAS and CLTEST.BAT
See also:
SetSwCh
____________________________
SETSWCH
Declaration:
procedure SetSwCh(C : char);
Purpose:
Sets the switch lead-in character to C.
Comments:
THIS PROCEDURE MODIFIES THE CURRENTLY RUNNING COPY OF DOS.
Therefore it should only be used in exceptional circumstances,
and with great caution. Otherwise the users could be in for quite
a surprise! It is included here primarily for completeness.
Examples:
SetSwCh('+');
will change the switch lead-in to '+'.
See also:
ReadSwCh
ShCmdLin 2-8
06/15/92 09:46am
ShCmplx
A Complex Arithmetic Unit
INTRODUCTION
ShCmplx is a complex arithmetic unit for Turbo Pascal,
version 5 or higher. It provides for the basic binary arithmetic
functions (addition, subtraction, multiplication, division), plus
the raising of a complex number to a real power. Conversion func-
tions are provided to convert between a complex number repre-
sented in Cartesian form and one represented in polar form.
Finally, provision is made to convert a complex number in
Cartesian form to a string; or a complex in polar form to a
string expressing the angle either in degrees or in radians.
All of the described functionality is available as a suite
of Pascal functions. All except the string conversion routines
are also available as Pascal procedures.
However, recall that a complex number C is represented by
two real numbers, say (R1, R2), where C = (R1 + i*R2) and i is
the square root of -1. Thus, the representation is inherently a
record structure. And Pascal functions can only return simple
data types - no structured types.
ShCmplx avoids this problem by storing all of its data on
the heap. When a variable is declared to be of type Complex, this
declaration establishes only a pointer in the data segment; the
record structure itself is established on the heap.
What this means in practice is that type complex, in this
package, is not defined as
type
Complex = record
Re,
Im : ComplexElement;
end;
but, rather, as
type
ComplexBaseType = record
Re,
Im : ComplexElement;
end;
Complex = ^ComplexBaseType;
ShCmplx 3-1
Thus, if we had an expression which we wished to evaluate -
for example:
A = A + B + C + D
this is able to be evaluated (where CAddF is the function name
for complex addition) as:
A^ := CAddF(CAddF(A, B), CAddF(C, D))^;
which is the equivalent of (with the pointers de-referenced)
A := ((A + B) + (C + D));
or
A^ := CAddF(A, CAddF(B, CAddF(C, D)))^;
which is the equivalent of (again, with the pointers de-
referenced)
A := (A + (B + (C + D)));
and the result of this calculation can be displayed using either
WriteLn(Cmp2Str(A, 8, 4));
or
WriteLn(Cmp2Str(CAddF(CAddF(A, B), CAddF(C, D)), 8, 4));
where the "8, 4" in each case carry the same significance as the
parameters used in printing real quantities; specifically, the
total field width and number of places to the right of the
decimal point (in this case, for each numeric component).
Note that
A := CAddF(B, C);
is normally not what you would want. This would assign the
returned pointer value to the pointer variable 'A', rather than
assigning the complex value pointed to by the returned pointer to
the element pointed to by 'A', which you would get by writing
A^ := CAddF(B, C)^;
This type of error is, unfortunately, not detectable by the
Pascal compiler, the run-time system, or at the level of any ap-
plication software. So you need to be careful that you don't do
it to yourself.
A test program (TESTCMPX.PAS) is included with the distribu-
tion set. Study it for ideas and specifics of how to use the
various functions.
ShCmplx 3-2
INTERFACED ELEMENTS
Types
=====
ComplexElement = extended;
ComplexBaseType = record
Re,
Im : ComplexElement;
end;
Complex = ^ComplexBaseType;
Routines
========
____________________________
C2P
Declarations:
procedure C2P(A : Complex; var Result : Complex);
function C2PF(A : Complex) : Complex;
Purpose:
Transforms a complex in Cartesian form into polar form.
Examples:
CpPwrR(C2PF(MyCmpx), 3.0, MyCmpxCubedPolar);
Comments:
The magnitude will be stored in Result^.Re and the angle
(expressed in radians) in Result^.Im
See Also:
P2C
ShCmplx 3-3
____________________________
CABS
Declarations:
procedure CAbs(A : Complex; var Result : ComplexElement);
function CAbsF(A : Complex) : ComplexElement;
Purpose:
Returns the absolute value of a complex number.
Examples:
∙∙∙
MyCmpx^.Re := 3.0;
MyCmpx^.Im := 4.0;
∙∙∙
WriteLn(CAbs(MyCmpx):4:1); {will display 5.0}
Comments:
Recall that the absolute value of a complex number Re + iIm
is sqrt((Re * Re) + (Im * Im)).
See Also:
____________________________
CADD
Declarations:
procedure CAdd(A, B : Complex; var Result : Complex);
function CAddF(A, B : Complex) : Complex;
Purpose:
Returns the sum of two complex numbers A + B.
Examples:
See the file TESTCMPX.PAS
Comments:
See Also:
CSub CMul CDiv
ShCmplx 3-4
____________________________
CCONJ
Declarations:
procedure CConj(A : Complex; var Result : Complex);
function CConjF(A : Complex) : Complex;
Purpose:
Returns the complex conjugate of a complex number.
Examples:
See the file TESTCMPX.PAS
Comments:
Recall that if a complex number A = R + Ii, then the complex
conjugate of A is R - Ii.
See Also:
____________________________
CDIV
Declarations:
procedure CDiv(A, B : Complex; var Result : Complex);
function CDivF(A, B : Complex) : Complex;
Purpose:
Returns the quotient of two complex numbers A / B.
Examples:
See the file TESTCMPX.PAS
Comments:
CAbsF(B) must be > 0.0. If CAbsF(B) <= 0.0, CmplxError will
return -1.
See Also:
CAdd CMul CSub
ShCmplx 3-5
____________________________
CMP2STR
Declarations:
function Cmp2Str(A : Complex; Width, Places : byte) :
string;
Purpose:
Converts a complex value to a string of the form
(Re + Im i)
Examples:
See the file TESTCMPX.PAS
Comments:
The Width and Places arguments have the same significance
that they do in the system procedure STR, and are applied
individually to both the REAL and IMAGINARY parts.
See Also:
CmpP2Str CmpP2StrD
____________________________
CMPLXERROR
Declarations:
function CmplxError : integer;
Purpose:
Returns execution error conditions for the package.
Examples:
See the file TESTCMPX.PAS
Comments:
Return = 0 OK
-1 Attempt to divide by zero (CDiv)
-2 Magnitude of complex is zero (CpPwrR)
See Also:
ShCmplx 3-6
____________________________
CMPP2STR
Declarations:
function CmpP2Str(A : Complex; Width, Places : byte) :
string;
Purpose:
Converts a complex in polar form to a string with the angle
expressed in radians.
Examples:
See the file TESTCMPX.PAS
Comments:
The Width and Places arguments have the same significance
that they do in the system procedure STR, and are applied
individually to both the MAGNITUDE and ANGLE parts.
See Also:
Cmp2Str CmpP2StrD
____________________________
CMPP2STRD
Declarations:
function CmpP2StrD(A : Complex; Width, Places : byte) :
string;
Purpose:
Converts a complex in polar form to a string with the angle
in degrees.
Examples:
See the file TESTCMPX.PAS
Comments:
The Width and Places arguments have the same significance
that they do in the system procedure STR, and are applied
individually to both the MAGNITUDE and ANGLE parts.
See Also:
Cmp2Str CmpP2Str
ShCmplx 3-7
____________________________
CMUL
Declarations:
procedure CMul(A, B : Complex; var Result : Complex);
function CMulF(A, B : Complex) : Complex;
Purpose:
Returns the product of two complex numbers A * B.
Example:
See the file TESTCMPX.PAS
Comments:
See Also:
CAdd CDiv CSub RxC
____________________________
CPPWRR
Declarations:
procedure CpPwrR(A : Complex; R : ComplexElement;
var Result : Complex);
function CpPwrRF(A : Complex; R : ComplexElement) : Complex;
Purpose:
Raises a complex (in polar form) to a real power.
Examples:
See the file TESTCMPX.PAS
Comments:
If A^.Re = 0, CmplxError will return -2, and
Result will be 0 + 0i
n.b. A^.Re contains the magnitude.
See Also:
ShCmplx 3-8
____________________________
CSUB
Declarations:
procedure CSub(A, B : Complex; var Result : Complex);
function CSubF(A, B : Complex) : Complex;
Purpose:
Returns the difference between two complex numbers A - B.
Examples:
See the file TESTCMPX.PAS
Comments:
See Also:
CAdd CDiv CMul
____________________________
P2C
Declarations:
procedure P2C(A : Complex; var Result : Complex);
function P2CF(A : Complex) : Complex;
Purpose:
Transforms a complex in polar form into Cartesian form. The
magnitude is stored in A^.Re and the angle (expressed in radians)
in A^.Im.
Examples:
See the file TESTCMPX.PAS
Comments:
See Also:
C2P
ShCmplx 3-9
____________________________
RXC
Declarations:
procedure RxC(A : ComplexElement; B : Complex;
var Result : Complex);
function RxCF(A : ComplexElement; B : Complex) : Complex;
Purpose:
Returns the complex product of a real and a complex.
Examples:
See the file TESTCMPX.PAS
Comments:
This is simply a special case of CMul, in which the
imaginary part of one of the factors is zero. It occurrs with
sufficient frequency, however, to warrent separate treatment.
See Also:
CMul
ShCmplx 3-10
06/15/92 09:46am
ShCrcChk
A File CRC16 Calculation Unit
INTRODUCTION
ShCrcChk interfaces two procedures, both of which calculates
the CRC16 of a file whose name is provided as a string parameter.
When the DOS COPY command is used, no true read-after-write
verification is performed. The only way to assure that the re-
cording was correct is to read the file after writing, and com-
pare the output file, byte for byte, with the input. For very
long files this can result in unacceptable delays.
A reasonable compromise between speed and reliability is to
calculate the cyclic redundancy check (CRC) word of the input
file as it is being copied, and then on completion of the copying
operation, read back the output file and calculate its CRC. If
the two compare, the probability that the two files differ is
extremely small, especially if the two files are of the same
size.
OVERVIEW
For those unfamiliar with CRCs, suffice to say that they are
very powerful generalizations of the familiar 'parity check'
schemes, such as those which have been used at least since the
early days of digital magnetic tape recording.
CRCs are calculated by performing iterative calculations,
byte by byte, on a data block, using specific algebraic poly-
nomials to determine the manner in which individual bits of each
byte are to be used in the calculation. The determination of
suitable polynomials is the subject of an extensive body of
literature.
The CCITT (for those who enjoy living life the hard way,
CCITT is the designation for the International Consultative
Committee for Telephone and Telegraph, a branch of the United
Nations) has recommended the use of a specific generator poly-
nomial for use in calculating the CRC for data blocks in asyn-
chronous communications. This polynomial is
(X^16 + X^12 + X^5 + 1).
ShCrcChk 4-1
While its recommended use primarily deals with block trans-
mission of data over asynchronous links (as in the X/Y/ZMODEM
protocols), it has come into widespread use also as a generator
polynomial for file-level CRC. This is therefore the generator
polynomial which has been used for ShCrcChk.
Those sufficiently interested and/or masochistic as to want
to find additional information regarding the theory of CRC are
referred to:
1. SOBOLEWSKI, J.S., "Cyclic Redundancy Check", in Ralston,
A. (ed.), Encyclopedia of Computer Science and Engineering (2nd
Ed.), Van Nostrand Reinhold Co., 1983, p.434ff
2. PLESS, V., "Introduction to the Theory of Error-
Correcting Codes", John Wiley and Sons, 1982, p. 59ff
Both of these references include bibliography for additional
study.
INTERFACED ELEMENTS
Routines
========
____________________________
CRCCALC
Declaration:
function CrcCalc(FileName : String) : word;
Purpose:
To calculate the CRC16 of a named file, assumed to exist.
Example:
if CrcCalc(MyFile) <> CrcShouldBe then begin
(*Take remedial action*)
end;
Comments:
MyFile is a file of any type, and may have any attributes
including Hidden, ReadOnly, etc. A run time error will result,
however, if the file does not exist.
ShCrcChk 4-2
____________________________
CRCCOPY
Declaration:
function CrcCopy(InFileName, OutFileName : String) : word;
Purpose:
Calculates the CRC16 value for file=InFileName, while
copying it to file=OutFileName.
Example:
CrcShouldBe := CrcCopy(FileFromYou, MyFile);
if CrcCopy(MyFile, '') <> CrcShouldBe then begin
(*Take remedial action*)
end;
Comments:
The output file name is optional. If OutFileName is speci-
fied, InFileName is copied to OutFileName. If OutFileName is an
empty string, CrcCopy behaves exactly like CrcCalc. In either
case, the CRC16 value of InFileName is returned.
Using CrcCopy simply to calculate the CRC16 of the input
file will be marginally slower than using CrcCalc. In cases in
which both functionalities are required, however, using CrcCopy
exclusively will result in a somewhat smaller code segment.
ShCrcChk 4-3
06/15/92 09:46am
This page has been deliberately left
blank, except for this message.
ShCrcChk 4-4
ShDatPk
A Date Manipulation Unit
INTRODUCTION
ShDatPk is a set of routines intended to simplify the
accurate manipulation of dates. These routines are based on
Algorithm #398 and associated comments, from the Collected
Algorithms of the ACM.
Originally distributed as DATEPACK for TURBO/PASCAL ver. 3
(and compatible with ver. 4), the routines relied heavily on Real
arithmetic. Re-written here for ver. 4 and above, all Real arith-
metic has been replaced by LongInt. This results in a speed-up of
nearly 60%, over the original DATEPACK routines compiled with
real arithmetic but without a math coprocessor.
Before proceeding, several definitions are necessary to
provide the framework for understanding the various conversions
possible through the use of the ShDatPk routines.
GREGORIAN DATE is the date system commonly used in modern
western nations. Established by Papal bull in
March 1582, it adjusted the calendar in use up to
that time in order to restore the vernal equinox
to March 21. This was accomplished by suppressing
the dates from the 5th through the 14th
(inclusive) of October, 1582. While the Gregorian
calendar was accepted quickly throughout most of
Europe, it was not adopted in England and the
Colonies until 1752. When YEAR, MONTH, and/or DAY
are passed or returned as parameters in the
ShDatPk routines, the Gregorian system is
assumed.
JULIAN DAY-NUMBER
JULIAN DAY is the representation of a given date as its
serial index, beginning on January 1, 4713 B.C.
The date chosen as the basis has astronomical
significance, and is widely recognized in the
scientific community. Proposed by the astronomer
Joseph Scaliger, it is named in memory of his
father and not, as often assumed, for Julius
Caesar. When used as a parameter by any of the
ShDatPk routines, it will be passed as a LongInt
representation of a 7 digit integer.
ShDatPk 5-1
JULIAN DATE is the representation of a given date as its
serial index, taking January 1st of the given
year as the base (=1). When used as a parameter by
any of the ShDatPk routines, both the serial index
and the year will be represented as simple
integers. (By the way, this one was named for
Julius Caesar).
SMITHSONIAN DATE
is the representation of a given date as its
serial index, with November 18, 1858 as the base
(=1). While routines are not included for
converting from or to the Smithsonian date, it is
readily calculated from the Julian Day as
Smithsonian = Julian - 2400001
INTERFACED ELEMENTS
Types
=====
GregType = record
Year : LongInt;
Month,
Day : byte;
end;
Variables of this type contain a complete Gregorian date,
and are passed to many of the routines in this unit.
TimeType = record
H,
M,
S : byte;
end;
Variables of this type contain a complete time record, and
are passed to many of the routines in this unit.
Constants
=========
DayStr : array[0..6] of string[9] =
('Sunday' , 'Monday' , 'Tuesday' ,
'Wednesday', 'Thursday' , 'Friday' ,
'Saturday' );
MonthStr: array[1..12] of string[9] =
('January' , 'February' , 'March',
'April' , 'May' , 'June',
'July' , 'August' , 'September',
'October' , 'November' , 'December');
ShDatPk 5-2
Routines
========
____________________________
DOW
Declaration:
function DoW(Greg : GregType) : byte;
Purpose:
To compute the day of the week (Sunday = 0; Saturday = 6)
from the Gregorian date.
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
GREG2ANSI
Declaration:
function Greg2ANSI(G : GregType) : string;
Purpose:
Given a Gregorian date, return the date as an ANSI date
string (YYYYMMDD).
Examples:
See TESTDATE.PAS
Comments:
Note that the ANSI date format is both sortable and
readable.
See also:
JDN2ANSI
ShDatPk 5-3
____________________________
GREG2JDATE
Declaration:
function Greg2JDate(Greg : GregType) : integer;
Purpose:
To compute the Julian date from the Gregorian date.
Examples:
See TESTDATE.PAS
Comments:
Do not confuse the Julian date with the Julian Day-Number.
The Julian date, most commonly used in business applications, is
the serial index of a date WITHIN A GIVEN YEAR. The Julian Day-
Number is the serial index of a date from January 1, 4713 B.C.
See also:
JDate2Greg
____________________________
GREG2JDN
Declaration:
function Greg2JDN(Greg : GregType) : LongInt;
Purpose:
To convert a Gregorian date into a Julian Day-Number.
Examples:
See TESTDATE.PAS
Comments:
The Julian Day-Number (JDN) is the basic form for date
manipulation within this unit. Thus this function performs the
primary conversion between dates in the customary form and
equivalent dates suitable for manipulation by ShDatPk.
See also:
JDN2Greg
ShDatPk 5-4
____________________________
JDATE2GREG
Declaration:
procedure JDate2Greg(JDate, Year : Integer;
var Greg : GregType);
Purpose:
To compute the Gregorian date from the Julian date.
Examples:
See TESTDATE.PAS
Comments:
Do not confuse the Julian date with the Julian Day-Number.
The Julian date, most commonly used in business applications, is
the serial index of a date WITHIN A GIVEN YEAR. The Julian Day-
Number is the serial index of a date from January 1, 4713 B.C.
See also:
Greg2JDate
____________________________
JDN2ANSI
Declaration:
function JDN2ANSI(JDN : LongInt) : string;
Purpose:
Given a Julian Day-Number, return the JDN as an ANSI date
string (YYYYMMDD).
Examples:
See TESTDATE.PAS
Comments:
Note that the ANSI date format is both sortable and
readable.
See also:
Greg2ANSI
ShDatPk 5-5
____________________________
JDN2GREG
Declaration:
procedure JDN2Greg(JDN : LongInt; var Greg : GregType);
Purpose:
To compute the Gregorian date from the Julian Day-Number.
Examples:
See TESTDATE.PAS
Comments:
The Julian Day-Number (JDN) is the basic form for date
manipulation within this unit. Thus this function performs the
primary conversion between dates in ShDatPk internal form and
equivalent dates in the customary form.
See also:
Greg2JDN
____________________________
GREG2STR
Declaration:
function Greg2Str(G : GregType; Delim : string) : string;
Purpose:
Returns a Gregorian date record as a string of the form
MMdDDdYYYY, where the separator, "d", is Delim[1].
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-6
____________________________
JDN2STR
Declaration:
function JDN2Str(JDN : LongInt; Delim : string) : string;
Purpose:
Returns a Julian Day-Number as a string of the form
MMdDDdYYYY, where the separator, "d", is Delim[1].
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
NOW
Declaration:
function Now : LongInt;
Purpose:
Returns the system time as Seconds-Since-Midnight.
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
NOW2TIME
Declaration:
procedure Now2Time(var T : TimeType);
Purpose:
Returns the system time as a Time record.
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-7
____________________________
NOWSTR
Declaration:
function NowStr(Delim : string; T24 : boolean) : string;
Purpose:
Returns the system time as a string of the form:
HHdMMdSSss if Delim is non-empty and T24 (24 hour time)
is false. The delimiter used, "d", is
Delim[1]. The suffix, "ss", is "am" or "pm" as
appropriate.
HHdMMdSS if Delim is non-empty and T24 (24 hour time)
is true. The delimiter used, "d", is Delim[1].
The time will be expressed in 24-hour form.
HHMMSSss if Delim is empty and T24 (24 hour time) is
false. The suffix, "ss", is "am" or "pm" as
appropriate.
HHMM if Delim is empty and T24 (24 hour time) is
true. The time will be expressed in 24-hour
form.
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
SSM2TIME
Declaration:
procedure SSM2Time(SSM : LongInt; var T : TimeType);
Purpose:
Converts Seconds-Since-Midnight to a Time record.
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-8
____________________________
SSM2TIMESTR
Declaration:
function SSM2TimeStr(SSM : LongInt; Delim : string;
T24 : boolean) : string;
Purpose:
Converts Seconds-Since-Midnight to a time string, of the
form:
HHdMMdSSss if Delim is non-empty and T24 (24 hour time)
is false. The delimiter used, "d", is
Delim[1]. The suffix, "ss", is "am" or "pm" as
appropriate.
HHdMMdSS if Delim is non-empty and T24 (24 hour time)
is true. The delimiter used, "d", is Delim[1].
The time will be expressed in 24-hour form.
HHMMSSss if Delim is empty and T24 (24 hour time) is
false. The suffix, "ss", is "am" or "pm" as
appropriate.
HHMM if Delim is empty and T24 (24 hour time) is
true. The time will be expressed in 24-hour
form.
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
TIME2SSM
Declaration
function Time2SSM(T : TimeType) : LongInt;
Purpose:
Converts a Time record to Seconds-Since-Midnight.
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-9
____________________________
TIME2TIMESTR
Declaratin:
function Time2TimeStr(T : TimeType; Delim : string;
T24 : boolean) : string;
Purpose:
Converts a time record to a time string of the form:
HHdMMdSSss if Delim is non-empty and T24 (24 hour time)
is false. The delimiter used, "d", is
Delim[1]. The suffix, "ss", is "am" or "pm" as
appropriate.
HHdMMdSS if Delim is non-empty and T24 (24 hour time)
is true. The delimiter used, "d", is Delim[1].
The time will be expressed in 24-hour form.
HHMMSSss if Delim is empty and T24 (24 hour time) is
false. The suffix, "ss", is "am" or "pm" as
appropriate.
HHMM if Delim is empty and T24 (24 hour time) is
true. The time will be expressed in 24-hour
form.
Examples:
See TESTDATE.PAS
Comments:
See also:
____________________________
TODAY
Declaration:
function Today : LongInt;
Purpose:
Returns the system date as a Julian Day-Number.
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-10
____________________________
TODAY2ANSI
Declaration:
function Today2ANSI : string;
Purpose:
Returns the system date as an ANSI date string (YYYYMMDD).
Examples:
See TESTDATE.PAS
Comments:
Note that the ANSI date format is both sortable and
readable.
See also:
____________________________
TODAY2GREG
Declaration:
procedure Today2Greg(var G : GregType);
Purpose:
Returns the system date as a Gregorian date record.
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-11
____________________________
TODAYSTR
Declaration:
function TodayStr(Delim : string) : string;
Purpose:
Returns the system date as a string of the form MMdDDdYYYY,
where the separator, "d", is Delim[1].}
Examples:
See TESTDATE.PAS
Comments:
See also:
ShDatPk 5-12
06/15/92 09:46am
ShErrMsg
An Error Message Handeling Unit
INTRODUCTION
"Runtime error 152 at 12C4:0B23" really is not all that
informative. How much better to see
Runtime error 152 - Drive not ready
Error at 1376:0003
If ShErrMsg is included LAST in the USES statement of your
program, any normal runtime errors will be reported along with a
brief message suggesting the problem.
During initialization, ShErrMsg installs a special exit
routine into the exit procedure chain maintained by Turbo PASCAL.
For the normal suite of runtime errors as listed in the manuals,
this exit routine will display the error information in the ex-
panded format shown above, with the explanatory message.
Further, ShErrMsg interfaces replacements for T-PASCAL's
HALT and RUNERROR procedures. These replacements, called HaltMsg
and RunErrorMsg, permit the programmer to display any desired
message along with the normal termination information reported by
the corresponding T-PASCAL routine.
ShErrMsg installs itself with checking ON; i.e., any errors
occurring during execution of your program which would normally
cause program termination will terminate with a message as de-
scribed above. Should you wish it, you can turn this facility off
and on again using the two procedures
CheckOff
CheckOn
If CheckOff has been executed, error reporting will appear
as if ShErrMsg had never been installed. The messages will not
appear. HaltMsg and RunErrorMsg will behave exactly as if Halt or
RunError had been called.
If checking is enabled, either by default or through execu-
tion of CheckOn, and procedure RunError is executed with an error
code not part of the normal suite, the message "Unknown Error
Code" will appear. RunErrorMsg will, of course, report whatever
message you have provided as part of the call.
ShErrMsg 6-1
ERROR ADDRESS REPORTING
If checking is enabled, or if RunErrorMsg is called (even if
checking is disabled), the error address reported will appear
slightly different than it normally would. ShErrMsg reports ad-
dresses normalized; the segment address is adjusted so that the
offset shown lies in the range
0 <= Ofs <= $F
If, however, you calculate the actual resulting 20-bit
addresses, you will find that they are identical.
INTERFACED ELEMENTS
Routines
========
____________________________
CHECKON
CHECKOFF
Declarations:
procedure CheckOn;
procedure CheckOff;
Purpose:
Enables/disables the error reporting facilities of ShErrMsg.
Examples:
∙∙∙
CheckOff; {Turn off error reporting}
∙∙∙
CheckOn; {Turn error reporting back on}
Comment:
The default state following initialization is CheckOn.
ShErrMsg 6-2
____________________________
HALTMSG
Declarations:
procedure HaltMsg(Code : word; Msg : string);
Purpose:
To stop execution of the program, returning an error code to
DOS and optionally displaying a message.
Examples:
∙∙∙
HaltMsg(1000, 'Exiting on a problem in procedure FOO_BAZ');
Comments:
If Checking is ON, execution will stop with the message, and
a return code of 1000 will be passed to DOS.
ErrorLevel 1000
Exiting on a problem in procedure FOO_BAZ
If checking is OFF, execution will stop with no message, and
a return code of 1000 will be passed to DOS.
In either case, due to the way in which DOS is implemented,
an
IF ERRORLEVEL
command will be sensitive ONLY TO THE LOW BYTE of the code. Thus,
in the above example, DOS will see a return code of 232.
See also:
RunErrorMsg
ShErrMsg 6-3
____________________________
RUNERRORMSG
Declarations:
procedure RunErrorMsg(Code : integer; Msg : string);
Purpose:
To stop execution of the program with a runtime error
message, optionally augmented by an additional information
message, and returning an error code to DOS.
Examples:
∙∙∙
RunErrorMsg(1000, 'Problem in procedure FOO_BAZ');
Comments:
If Checking is ON, execution will stop with the following
message, and a return code of 1000 will be passed to DOS.
Runtime error 1000 at 0C8F:0008
Problem in procedure FOO_BAZ
If checking is OFF, execution will stop with the following
message, and a return code of 1000 will be passed to DOS.
Runtime error 232 at 0000:C8F8
In either case, due to the way in which DOS is implemented,
an
IF ERRORLEVEL
command will be sensitive ONLY TO THE LOW BYTE of the code. Thus,
in the above example, DOS will see a return code of 232.
Note also that, if checking if turned off, the error address
is not normalized.
See also:
HaltMsg
ShErrMsg 6-4
06/15/92 09:46am
ShFinanc
A Financial Calculations Unit
INTRODUCTION
ShFinanc is a unit containing six functions necessary to
perform most ordinary financial calculations. Specifically,
CompPresVal = compound present value,
CompAmount = compound amount,
AnnuityPresVal
= annuity present value,
AnnuityAmount = annuity amount,
NumPay = number of payments corresponding to a given
annuity present value and interest rate, and
IfromPresVal = interest rate corresponding to a given
annuity present value and number of payments.
The parameter list for the four functions dealing with
annuities contain a switch which dictates whether the calcula-
tions are to be carried out for an ordinary annuity (payments
made at the end of each conversion period) or an annuity due
(payments made at the beginning of each conversion period).
INTERFACED ELEMENTS
Types
=====
AnnType = (Ordinary, Due);
Constants
=========
finOK = 0;
finErrParamTooSmall = 200;
finIntOutOfRange = 201;
finIllegalNumPeriods = 202;
finUnknownAnnuityType = 203;
finIllegalPresentValue = 204;
fin80x87error = 205;
finNoConvergence = 206;
finIndeterminateForm = 207;
ShFinanc 7-1
{80x87 errors}
finInvalidOperation = 1;
finDenormalizedOperand = 2;
finDivideByZero = 4;
finOverflow = 8;
finUnderflow = 16;
FW = 17;
DP = 10;
IW = 6;
Variables
=========
finError,
fin87error : word;
Routines
========
____________________________
ANNUITYAMOUNT
Declaration:
function AnnuityAmount(N : integer;
I : extended;
AType : AnnType) : extended;
Purpose:
To calculate the annuity amount of 1 for N periods at an
interest rate of I.
Examples:
Comments:
The annuity may be either ordinary or due, depending on the
value of AType.
See also:
AnnuityPresVal NumPay IfromPresVal
ShFinanc 7-2
____________________________
ANNUITYPRESVAL
Declaration:
function AnnuityPresVal(N : integer;
I : extended;
AType : AnnType) : extended;
Purpose:
To calculate the annuity present value of 1 for N periods at
an interest rate of I.
Examples:
Comments:
The annuity may be either ordinary or due, depending on the
value of AType.
See also:
AnnuityAmount NumPay IfromPresVal
____________________________
COMPAMOUNT
Declaration:
function CompAmount(N : integer; I : extended;) : extended;
Purpose:
To calculate the compound amount of 1 for N periods at an
interest rate of I.
Examples:
Comments:
See also:
CompPresVal
ShFinanc 7-3
____________________________
COMPPRESVAL
Declaration:
function CompPresVal(N : integer; I : extended;) : extended;
Purpose:
To calculate the compound present value of 1 for N periods
at an interest rate of I.
Examples:
Comments:
See also:
CompAmount
____________________________
FIN87ERRCODE
Declaration:
function fin87errCode : word;
Purpose:
If finErrCheckOff has been turned off and if finErrCode =
fin80x87error, then fin87errCode will return the 80x87 error code
resulting from the last call to a financial routine, and will
reset the internal 80x87 error variable to 0 (finOK).
Examples:
Comments:
fin87errCode should be called whenever a call to finErrCode
returns a value of fin80x87error.
See also:
finErrChkOff finErrCheckOn finErrCode
finErrMsg
ShFinanc 7-4
____________________________
FINERRCHECKON
Declaration:
procedure finErrCheckOn;
Purpose:
To turn error checking ON within the shFinanc unit.
Examples:
Comments:
Following a call to finErrCheckOn, any errors occurring in
any of the routines of shFinanc will cause program termination
with an appropriate error message.
The default value is ON.
See also:
fin87ErrCode finErrCheckOff finErrCode
finErrMsg
____________________________
FINERRCHECKOFF
Declaration:
procedure finErrCheckOff;
Purpose:
To turn error checking OFF within the shFinanc unit.
Examples:
Comments:
Following a call to finErrCheckOff, any errors occurring in
any of the routines of shFinanc will not cause program
termination, but any error will be available through a call to
finErrCode and the corresponding message will be available
through a call to finErrMsg.
The default value is ON.
See also:
fin87ErrCode finErrCheckOn finErrCode
finErrMsg
ShFinanc 7-5
____________________________
FINERRCODE
Declaration:
function finErrCode : word;
Purpose:
If finErrCheckOff has been turned off, finErrCode will re-
turn the error code resulting from the last call to a financial
routine, and will reset the internal error variable to 0 (finOK).
Examples:
Comments:
As with the Turbo Pascal function IoResult, finErrCode
should be called after each call to a financial routine.
See also:
fin87ErrCode finErrChkOff finErrCheckOn
finErrMsg
____________________________
FINERRMSG
Declaration:
function finErrMsg(Code : word) : string;
Purpose:
To return the message corresponding to a given error code.
Examples:
The code
APV := AnnuityPresentValue(100, -0.95, Ordinary);
S := finErrMsg(finErrCode);
will result in S conatining the string
'Interest parameter out of range.'
Comments:
See also:
fin87errCode finErrChkOff finErrCheckOn
finErrCode
ShFinanc 7-6
____________________________
IFROMPRESVAL
Declaration:
function IfromPresVal(PresVal : extended;
N : integer;
AType : AnnType;
Err : extended) : extended;
Purpose:
To calculate the interest rate of an annuity of 1 whose
present value is PresVal for N payments.
Examples:
Comments:
The annuity may be either ordinary or due, depending on the
value of AType.
Err is the maximum allowable absolute error of calculation.
If the unit is compiled with {$N+}, then Err must be >= 1.0E-16.
If compiled with {$N-}, then Err must be >= 1.0E-9.
See also:
____________________________
NUMPAY
Declaration:
function NumPay(PresVal,
I : extended;
AType : AnnType) : integer;
Purpose:
To calculate the number of periods needed to retire a mort-
gage of 1 whose present value is PresVal at an interest rate of I
per period.
Examples:
Comments:
The annuity may be either ordinary or due, depending on the
value of AType.
See also:
AnnuityPresVal IfromPresVal
ShFinanc 7-7
This page has been deliberately left
blank, except for this message.
ShFinanc 7-8
ShList
A List Manipulation Unit
INTRODUCTION
Lists, rings, and stacks are among the most common data
structures used (after arrays). They are also probably among the
worst offenders when it comes to "re-inventing the wheel." Many
programmers build special purpose list manipulation routines each
time a list is needed. Obviously, a generic list manipulation
package is a valuable addition to the available "bag of tricks."
ShList contains all of the routines necessary to establish
and manipulate singly and doubly linked lists, rings, and stacks.
The data associated with any given list, ring, or stack can be
any standard or user defined data type. The structure of the data
can change, but the total length of the data must remain con-
stant. Thus, for example, variant records can be used.
Stacks do not constitute a separate entity; their establish-
ment and manipulation is accomplished by setting up a singly
linked list, and restricting oneself to slPush and slPop respec-
tively for data storage and retrieval.
Rings also do not constitute a separate entity. Both the
singly and doubly linked list are, in fact, treated as rings.
When traversing a list of either type (e.g., using xxGetNext),
retrieval will fail with the next call following retrieval of the
last list element. If xxGetNext is called again, however, the
element at the head of the list will be retrieved. Thus, the
entity has all the functionality of a ring.
NOMENCLATURE
The names of the routines within ShList which apply to
singly linked lists are prefixed with the letters "sl", as
"slPut", "slAppend", etc. Those applying to doubly linked lists
have a "dl" prefix.
Many of the routines have identical functions, and differ
only in the type of entity which they manipulate. Such routines
have similar names, differing only in the prefix as described
above; for example (slPut, dlPut), (slPush, dlPush). These will
be discussed together in the following documentation.
ShList 8-1
In most cases, the call to a routine will have as one of its
parameters an untyped "var" parameter called DataRec. The data to
be placed on or retrieved from the list is passed to/from the
routine through this parameter. Since it is an untyped parameter,
it is up to you to make sure that the data being passed is of the
proper length and structure. Examples are provided with the
description of each routine.
!!CAUTIONARY NOTE!!
MARK/RELEASE must not be used for heap management when
using this unit. GETMEM/FREEMEM or NEW/DISPOSE must be
used instead.
!!END OF CAUTIONARY NOTE!!
INTERFACED ELEMENTS
Types
=====
slNodePtr = ^slNode;
slNode = record
Data : pointer;
Next : slNodePtr;
end;
dlNodePtr = ^dlNode;
dlNode = record
Data : pointer;
Next,
Prev : dlNodePtr;
end;
These are the basic node structures of the nodes for singly
and doubly linked nodes. They will be of no particular interest
to you unless you need to modify the code of the unit.
ShList 8-2
slList = record
DataRecSize : word;
Count : LongInt;
Head,
Tail,
Current : slNodePtr;
end;
dlList = record
DataRecSize : word;
Count : LongInt;
Head,
Tail,
Current : dlNodePtr;
end;
These are the structures of the singly and doubly linked
lists, respectively. You will be passing a variable of one of
these types to almost all of the routines in the unit. The actual
details of the structure need not concern you, however, unless
you need to modify the code of the unit.
dlLessFunc = function(var DataRec1, DataRec2) : boolean;
This is the form of a function which you will need to con-
struct if you are using the dlPutSorted routine. It is used to
determine the sort order of your data records. Its use is identi-
cal in concept to the "less" function of the TurboSort, TpSort,
or OpSort units.
ShList 8-3
Routines
========
Many of the routines have identical functions, and differ
only in the type of entity which they manipulate. These will be
discussed together in the following documentation.
The following routines are interfaced in ShList. They are
arranged alphabetically by basic function or routine name.
____________________________
APPEND
Declarations:
function slAppend(var L : slList; var DataRec) : boolean;
function dlAppend(var L : dlList; var DataRec) : boolean;
Purpose:
Appends a data record to an existing list. If the list is
empty, Append simply places the record in the list.
Comments:
The list must have been initialized prior to calling Append.
Append returns a value of "false" if insufficient heap space is
available for allocation of the node and data record.
Example:
if not slAppend(MyList, MyDataRecord) then begin
{Execute your recovery code}
end;
See Also:
Put, PutPrev, PutSorted, Push
ShList 8-4
____________________________
COUNT
Declarations:
function slCount(L : slList) : LongInt;
function dlCount(L : dlList) : LongInt;
Purpose:
Returns the number of items currently in the list.
Comments:
The item count is maintained continuously within the list
structure, so it is not necessary to scan the list in order to
generate the count.
Example:
for T1 := 1 to slCount(MyList) do begin
if slPop(MyList, MyDataRec) then ;
(* Now process the record *)
end; {for T1 := ...}
This code will process each record in the list, and the list
will be left empty on loop exit.
____________________________
FREE
Declarations:
procedure slFree(var L : slList);
procedure dlFree(var L : dlList);
Purpose:
Releases the heap space allocated for a list and its data.
Comments:
This procedure should be called as soon as you have com-
pleted your operations on the specified list. The list must be
re-initialized if it is to be reused.
Example:
slFree(MyList);
All heap space associated with "MyList" is released, follow-
ing which all the internal pointers of "MyList" are set to "nil"
and the associated data record length is set to zero.
See Also:
Init
ShList 8-5
____________________________
GETCURRENT
Declarations:
function slGetCurrent(var L : slList;
var DataRec) : boolean;
function dlGetCurrent(var L : dlList;
var DataRec) : boolean;
Purpose:
Returns the data record at the current node and does not
move the node pointer. Returns a function value of false if the
list is empty or the current node pointer is nil.
Comments:
This is essentially a "reread" operation. Normally, the cur-
rent node pointer will have been positioned during the course of
some other operation (e.g., GetFirst) and the data record will
have been returned as a result of that prior operation.
Example:
if not slGetCurrent(MyList, MyDataRec) then begin
{Trying to read an empty list.}
end;
See Also:
GetFirst GetNext GetLast GetPrev
____________________________
GETFIRST
Declarations:
function slGetFirst(var L : slList; var DataRec) : boolean;
function dlGetFirst(var L : dlList; var DataRec) : boolean;
Purpose:
Returns the data record at the head of the list. Sets the
current node pointer to the head of the list. Returns a function
value of false if the list is empty.
Comments:
Example:
if not slGetFirst(MyList, MyDataRec) then begin
{Trying to read an empty list.}
end;
See Also:
GetCurrent GetNext GetLast GetPrev
ShList 8-6
____________________________
GETLAST
Declarations:
function slGetLast(var L : slList; var DataRec) : boolean;
function dlGetLast(var L : dlList; var DataRec) : boolean;
Purpose:
Returns the data record at the tail of the list. Sets the
current node pointer to the tail of the list. Returns a function
value of false if the list is empty.
Comments:
Example:
if not slGetLast(MyList, MyDataRec) then begin
{Trying to read an empty list.}
end;
See Also:
GetCurrent GetFirst GetNext GetPrev
ShList 8-7
____________________________
GETNEXT
Declarations:
function slGetNext(var L : slList; var DataRec) : boolean;
function dlGetNext(var L : dlList; var DataRec) : boolean;
Purpose:
Returns the next data record in the list. Sets the current
node pointer to the record retrieved. Returns a function value of
false if the list is empty or if the last record successfully
retrieved was at the list tail. In this latter case, calling
slGetNext or dlGetNext again will retrieve the head of the list.
Comments:
Example:
{The following example assumes boolean short-circuiting ($B-)}
if (not slGetNext(MyList, MyDataRec))
{slGetNext false means an empty list or end of list}
and slGetNext(MyList, MyDataRec) then begin
{processing the head of the list}
end
else begin
{processing the normal "next" element in the list}
end;
See Also:
GetCurrent GetFirst GetLast GetPrev
ShList 8-8
____________________________
GETPREV
Declarations:
function dlGetPrev(var L : dlList; var DataRec) : boolean;
Purpose:
Same as dlGetNext, but in the opposite direction. Returns
the previous data record in the list. Sets the current node
pointer to the record retrieved. Returns a function value of
false if the list is empty or if the last record successfully
retrieved was at the list head. In this latter case, calling
dlGetPrev again will retrieve the tail of the list.
Comments:
Note that the GetPrev operation can only be performed on
doubly linked lists. There is no equivalent operation for singly
linked lists.
Example:
{The following example assumes boolean short-circuiting ($B-)}
if (not dlGetPrev(MyList, MyDataRec))
{dlGetPrev false means an empty list or top of list}
and dlGetPrev(MyList, MyDataRec) then begin
{processing the tail of the list}
end
else begin
{processing the normal "prior" element in the list}
end;
See Also:
GetCurrent GetFirst GetLast GetNext
ShList 8-9
____________________________
LISTINIT
Declarations:
procedure slListInit(var L : slList; RecSize : word);
procedure dlListInit(var L : dlList; RecSize : word);
Purpose:
Initializes a singly or doubly linked list, as appropriate.
Comments:
The list initialization routines initialize only the vari-
ables of type slList or dlList. They perform no memory alloca-
tion. Memory allocation is performed only by the various PUT
routines.
The ListInit routines **must** be called before any attempt
is made to place any data in, or retrieve any data from any
LIST-type variable. Also, once an initialized list has received
data, ListInit **must not** be called prior to a call to Free.
Failure to observe either of these warnings will produce
unpredictable but probably disastrous results.
Example:
slListInit(MyList);
See Also:
Free
ShList 8-10
____________________________
POP
Declarations:
function slPop(var L : slList; var DataRec) : boolean;
function dlPop(var L : dlList; var DataRec) : boolean;
Purpose:
Returns the data record at the head of the list, then deal-
locates the space associated with the data record and node. Re-
turns a function value of false if the list is empty.
Comments:
Example:
while slPop(MyList, MyDataRec) do begin
{process the retrieved record}
end;
This code will retrieve each record on the list and free up
the space associated with each, as it is retrieved. You will end
up with an empty list.
See Also:
Push Free
____________________________
PUSH
Declarations:
function slPush(var L : slList; var DataRec) : boolean;
function dlPush(var L : dlList; var DataRec) : boolean;
Purpose:
Pushes a data record onto the top of the list. Returns a
function value of false if there is insufficient heap space to
accommodate the list node and data record.
Comments:
Example:
if not slPush(MyList, MyDataRec) then begin
{perform recovery operations}
end;
See Also:
Append Put PutPrev PutSorted Pop
ShList 8-11
____________________________
PUT
Declarations:
function slPut(var L : slList; var DataRec) : boolean;
function dlPut(var L : dlList; var DataRec) : boolean;
Purpose:
Inserts a data record following the current node; returns
with current pointer directed to the new node. Returns a function
value of false if there is insufficient heap space to accommodate
the list node and data record.
Comments:
Example:
if not slPut(MyList, MyDataRec) then begin
{perform recovery operations}
end;
See Also:
Append Push PutPrev PutSorted Pop
____________________________
PUTPREV
Declarations:
function dlPutPrev(var L : dlList; var DataRec) : boolean;
Purpose:
Inserts a data record ahead of the current node; returns
with current pointer directed to the new node. Returns a function
value of false if there is insufficient heap space to accommodate
the list node and data record.
Comments:
Note that the PutPrev operation can only be performed on
doubly linked lists. There is no equivalent operation for singly
linked lists.
Example:
if not dlPutPrev(MyList, MyDataRec) then begin
{perform recovery operations}
end;
See Also:
Append GetPrev Push Put PutSorted
ShList 8-12
____________________________
PUTSORTED
Declarations:
function dlPutSorted(var L : dlList; var DataRec;
Less : dlLessFunc) : boolean;
Purpose:
Inserts a data record into the list in sorted order, as
determined by the user-defined boolean function LESS. Returns a
function value of false if there is insufficient heap space to
accommodate the list node and data record.
Comments:
The function LESS is a user-defined boolean function whose
declaration **must** be of the form
function Less(var Rec1, Rec2) :boolean;
and **must** be compiled under the FAR model.
Note that the PutSorted operation can only be performed on
doubly linked lists. There is no equivalent operation for singly
linked lists.
Note also that, to build the sorted list in descending order
rather than ascending, it is only necessary to reverse the sense
of the inequality in the comparison function.
Example:
{$F+}
function MyLess(var MyRec1, MyRec2) : boolean;
begin
MyLess := (MyRecType(MyRec1).FieldA <
MyRecType(MyRec2).FieldA);
end;
{$F-}
...
if not dlPutSorted(MyList, MyDataRec, @MyLess) then begin
{do something}
end;
Incorrect!!! The @-symbol cannot be used here.
if not dlPutSorted(MyList, MyDataRec, MyLess) then begin
{do something}
end;
Correct. Only the function name is passed.
See Also:
Append GetPrev Push Put PutPrev
ShList 8-13
____________________________
SPACEUSED
Declarations:
function slSpaceUsed(L : slList) : LongInt;
function dlSpaceUsed(L : dlList) : LongInt;
Purpose:
Returns the total amount of heap space currently allocated
to the list and its data.
Comments:
Example:
WriteLn(slSpaceUsed(MyList), ' total bytes used');
See Also:
Count
ShList 8-14
06/15/92 09:46am
ShLngStr
A Long String Manipulation Unit
INTRODUCTION
ShLngStr is a unit which provides the ability to manipulate
long strings (up to 65517 characters in length) using Turbo Pas-
cal. As such, it owes a debt to the Tp/OpASCIIZ units published
by TurboPower Software. Unlike the ASCIIZ manipulation units,
however, it carries its dynamic string length information in a
WORD at the beginning of the string. As such, it owes a debt to
the TpWrdStr unit written by Ken Henderson.
Both TpWrdStr and Tp/OpASCIIZ require a careful tradeoff on
the part of the user. They both typically allocate an "array of
char" in the data segment, in which the string data are stored;
thus they both define a MaxSize constant which must be carefully
balanced between providing a maximum string length long enough to
get the job done, and one which is small enough to avoid using up
the entire data segment.
ShLngStr avoids this problem. ShLngStr stores all of its
string data on the heap. When a variable is declared to be of
type LongString, this declaration establishes only a pointer in
the data segment. The LongString must then be initialized prior
to use. This initialization establishes a maximum allowable
string length, which may now vary from one LongString to the
next. Only the amount of heap space required for the initialized
maximum length is used. In this respect, the analog of a string
declaration of, for example, "var string[127];" has been pre-
served. Any of the procedures and functions in this unit will
observe the "declared" maximum length, and will adjust their
behavior appropriately
Thus, although a MaxLongString constant is included in the
unit, its value is set to the maximum allowable value (65517) and
is used only by lsInit.
Notwithstanding any of the above, the code in ShLngStr is
completely our own. Any bugs or deficiencies cannot be blamed on
anyone other than Madison & Associates.
ShLngStr 9-1
OVERVIEW
There are currently approximately 80 procedures and func-
tions available within the ShLngStr unit. With few exceptions,
each procedure has a corresponding function; e.g., procedure
lsStr2LongString which converts a string to a LongString has a
corresponding function lsStr2LongStringF. It is important to
remember that the functions which return a LongString are return-
ing a pointer value rather than the contents of the LongString
itself. Failure to account for this can result in rather startl-
ing results on occasion.
Function results (i.e., these pointers) are stored in a ring
buffer which is allocated as needed, and is only reallocated when
the ring pointer comes back around to the specific element. By
default, the number of elements in the ring is set to 25. This
should be sufficient for most purposes; should it prove insuffi-
cient, set the typed constant RingSize to a larger value and re-
compile. Alternatively, RingSize can be increased at execution
time to a maximum value of 100; it should NOT be decreased at
execution time, however. It can be set to a maximum of 100
without affecting the size of the data segment.
Since the data associated with function (pointer) returns
are accessible only through elements in the ring buffer, and
since the heap space used to store these data will be released
when the ring element is required for reuse, it is important that
these data be used as quickly as possible. They ain't gonna be
around forever!
Thus, the rule of thumb should be "when in doubt, use
procedure calls."
!!CAUTIONARY NOTE!!
MARK/RELEASE must not be used for heap management when
using this unit. GETMEM/FREEMEM or NEW/DISPOSE must be
used instead.
!!END OF CAUTIONARY NOTE!!
ShLngStr 9-2
INTERFACED ELEMENTS
Types
=====
NOTE: Because of the way in which LongStringType is
defined, if the ShLngStr unit is recompiled, range
checking MUST be turned off ({$R-}). Note also that
redefining the lsData field as array[1..MaxLongString]
is apt to cause other problems. This redefinition is
definitely NOT RECOMMENDED!
LongStringType = record
Length, {Dynamic length}
dLength : word; {"Declared" length}
lsData : array[1..1] of char;
end;
The record structure allocated on the heap for the storage
of LongString data.
LongString = ^LongStringType;
The type expected as actual parameters to the routines in
this unit; also, the type returned by most of the functions.
lsCompType = (Less, Equal, Greater);
The type returned by the LongString comparison functions.
lsDelimSetType = set of char;
The type of the set of characters which the GetNext routines
will use as word delimiters.
CharSet = set of Char;
Constants
=========
RingSize : byte = 25;
The number of elements in the ring buffer, used to store
pointers returned by function calls of type LongString. This
value may be freely increased to a maximum value of 100 during
program execution, if necessary. Decreasing it, however, could
result in orphan blocks allocated on the heap, with no way to
recover them.
lsDelimSet : lsDelimSetType = [#0..#32];
The typed constant used by the GetNext routines to determine
the end of a substring to be returned. It may be freely changed
during program execution.
ShLngStr 9-3
MaxLongString = 65517;
The maximum length of a LongString.
NotFound = 0;
Returned by the lsPos functions if a substring is not found.
Nomenclature
============
All interfaced routines in ShLngStr have "ls" as the first
two characters of their name.
In the descriptive listings which follow, all routines hav-
ing similar functionality are grouped, and all routines within a
group have names which differ only in their respective suffixes;
e.g.,
lsDelAll
lsDelAllF
lsDelAllStr
lsDelAllStrF
lsDelAllUC
lsDelAllUCF
lsDelAllStrUC
lsDelAllStrUCF
These routines delete all occurrences of an entity from a
LongString. The basic procedure, lsDelAll, takes three parameters
of type LongString; respectively, the input LongString containing
the data to be scanned, the input LongString containing the
entity to be deleted from the first, and the output LongString
which is a copy of the input data LongString with all occurrences
of the second parameter deleted.
The "F" suffixes on the second, fourth, sixth, and eighth
names indicate a function call returning the output LongString.
The "Str" suffix on the third, fourth, seventh, and eighth
names indicates that the entity to be deleted is a string rather
than a LongString.
The "UC" suffix on the fifth through the eighth names
indicate that searching and deletion will be performed all in
upper case; the searching will not be case sensitive.
Some functions exist which do not have the "F" suffix. In
each such case, the returned value is a normal Turbo Pascal data
type, specifically, WORD or STRING.
In the following, the ordering is alphabetic by primary
routine name.
ShLngStr 9-4
Routines
========
____________________________
lsCENTER
Declarations:
procedure lsCenter
(A: LongString; Width: word; B: LongString);
function lsCenterF
(A: LongString; Width: word): LongString;
Purpose:
Return a LongString centered in a LongString of blanks with
specified width.
Examples:
If A contains "abcdefg"
then lsCenter(A, 13, B);
results in B containing " abcdefg "
Comments:
If the length of A already exceeds Width, A will be returned
unchanged.
See Also:
lsCenterCh
ShLngStr 9-5
____________________________
lsCENTERCH
Declarations:
procedure lsCenterCh
(A: LongString; Ch: Char; Width: word; B: LongString);
function lsCenterChF
(A: LongString; Ch: Char; Width: word): LongString;
Purpose:
Return a LongString centered in a LongString of Ch with spe-
cified width.
Examples:
If A contains "abcdefg"
then lsCenterCh(A, '+', 13, B);
results in B containing "+++abcdefg+++"
Comments:
If the length of A already exceeds Width, A will be returned
unchanged.
See Also:
lsCenter
____________________________
lsCHARSTR
Declarations:
procedure lsCharStr
(Ch: Char; Len: word; A: LongString);
function lsCharStrF
(Ch: Char; Len: word): LongString;
Purpose:
Return a LongString of length Len filled with Ch.
Examples:
The call lsCharStr('+', 10, A);
results in A containing "++++++++++"
Comments:
If Len is greater than the maximum length of A, the returned
LongString will be equal in length to the maximum length of A.
See Also:
ShLngStr 9-6
____________________________
lsCOMP
Declarations:
function lsComp
(A1, A2: LongString): lsCompType;
Purpose:
Compares A1 to A2, returning LESS, EQUAL, or GREATER.
Examples:
For a normal COMPARE,
case lsComp(LS1, LS2) of
LESS : {Do This}
EQUAL : {Do That}
GREATER : {Do The Other}
end; {case lsComp}
For a case-insensitive COMPARE,
case lsComp(lsUpcaseF(LS1), lsUpcaseF(LS2)) of
LESS : {Do This}
EQUAL : {Do That}
GREATER : {Do The Other}
end; {case lsComp}
Comments:
This function completely implements the analog of the string
comparison operators of Turbo Pascal.
See Also:
ShLngStr 9-7
____________________________
lsCONCAT
Declarations:
procedure lsConcat
(A, B, C: LongString);
function lsConcatF
(A, B: LongString): LongString;
procedure lsConcatLs2Str
(S: string; A: LongString; C: LongString);
function lsConcatLs2StrF
(S: string; A: LongString): LongString;
procedure lsConcatStr2Ls
(A: LongString; S: string; C: LongString);
function lsConcatStr2LsF
(A: LongString; S: string): LongString;
Purpose:
Concatenate the second parameter to the end of the first.
Examples:
If A contains "abcdefg"
and B contains "hijklmn"
then lsConcat(A, B, C);
results in C containing "abcdefghijklmn"
Comments:
See Also:
ShLngStr 9-8
____________________________
lsCOPY
Declarations:
procedure lsCopy
(A: LongString; Start, Len: word; B: LongString);
function lsCopyF
(A: LongString; Start, Len: word): LongString;
Purpose:
Return a LongString substring of A. The substring begins at
position Start of A and will be of length Len.
Examples:
If A contains "abcdefg"
then lsCopy(A, 4, 3, B);
results in B containing "def"
If A contains "abcdefg"
then lsCopy(A, 4, 10, B);
results in B containing "defg"
Comments:
Start=1 for first char in A.
If Start > lsLength(A), an empty LongString will be
returned.
If Start+Len exceeds the length of A, the returned
LongString will be of length lsLength(A)-Start+1.
See Also:
ShLngStr 9-9
____________________________
lsCOUNT
Declarations:
function lsCount
(A, Obj: LongString): word;
function lsCountStr
(A: LongString; Obj: string): word;
function lsCountStrUC
(A: LongString; Obj: string): word;
function lsCountUC
(A, Obj: LongString): word;
Purpose:
Returns the total number of non-overlapping occurrences of
Obj in A.
Examples:
if lsCountStrUC(MyLS, 'abc') <> NotFound then {Do something}
If A contains "abcdeabcdeabcde"
and Obj contains "BCD"
then lsCount(A, Obj)
returns NotFound ( = 0 )
but lsCountUC(A, Obj)
returns 3
Comments:
If Obj is not a substring of A, returns NotFound (i.e., 0).
See Also:
ShLngStr 9-10
____________________________
lsDELALL
Declarations:
procedure lsDelAll
(A, Obj, B: LongString);
function lsDelAllF
(A, Obj: LongString): LongString;
procedure lsDelAllStr
(A: LongString; Obj: string; B: LongString);
function lsDelAllStrF
(A: LongString; Obj: string): LongString;
procedure lsDelAllStrUC
(A: LongString; Obj: string; B: LongString);
function lsDelAllStrUCF
(A: LongString; Obj: string): LongString;
procedure lsDelAllUC
(A, Obj, B: LongString);
function lsDelAllUCF
(A, Obj: LongString): LongString;
Purpose:
Deletes all occurrences of Obj in A.
Examples:
See below.
Comments:
Should the deletion of Obj from A result in a new occurrence
of Obj in A, the new occurrence will not be deleted, e.g.,
If A contains 'aabcbcabcd'
and Obj contains 'abc'
then lsDelAll(A, Obj, B);
results in B containing 'abcd'
and not 'd'
To delete all occurrences including such incidental
occurrences, one would use, e.g.,
repeat
lsDelAll(A, Obj, A);
until lsCount(A, Obj) = 0;
See Also:
lsRepAll lsCount
ShLngStr 9-11
____________________________
lsDELETE
Declarations:
procedure lsDelete
(A: LongString; Start, Len: word; B: LongString);
function lsDeleteF
(A: LongString; Start, Len: word): LongString;
Purpose:
Delete Len characters of A, starting at position Start.
Examples:
If A contains "abcdefg"
then lsDelete(A, 4, 3, B);
results in B containing "abcg"
If A contains "abcdefg"
then lsDelete(A, 4, 10, B);
results in B containing "abc"
Comments:
If Start is greater than the length of A, B = A on output.
See Also:
lsDelAll lsRepAll
____________________________
lsDISPOSE
Declarations:
procedure lsDispose
(var A: LongString);
Purpose:
Dispose of A, releasing its heap space.
Examples:
The call lsDispose(A);
results in All heap space associated with A is released
and A = nil
Comments:
See Also:
lsInit
ShLngStr 9-12
____________________________
lsGETNEXT
Declarations:
procedure lsGetNext
(LS1, LS2: LongString);
function lsGetNextF
(LS1: LongString): LongString;
procedure lsGetNextStr
(LS1: LongString; var S2: string);
function lsGetNextStrF
(LS1: LongString): string;
Purpose:
Returns the next substring of LS1 which is delimited by a
member of lsDelimSet.
Examples:
If A contains "abc def ghi jkl"
then the two calls
lsGetNext(A, B);
lsGetNext(A, B);
result in A containing " ghi jkl"
and B containing "def"
Comments:
On return, LS1 is returned untrimmed, but with the first
matching substring deleted.
See Also:
ShLngStr 9-13
____________________________
lsINIT
Declarations:
function lsInit
(var A: LongString; L: word): boolean;
Purpose:
"Declares" a LongString of maximum declared length L and
establishes space for it on the heap.
Examples:
The call if lsInit(A, 750) then {Do something};
results in a. A returned function value of "true"
b. 754 bytes being allocated on the heap.
(750 bytes for the character string,
4 overhead bytes.)
c. A containing a pointer to the heap space.
The call lsInit(A, 65518); {MaxLongString = 65517}
results in a. A returned function value of "false"
b. No space allocation on the heap.
c. A = nil
Comments:
Returns false if L is greater than MaxLongString.
If there is insufficient heap space to accommodate the
LongString, the program will terminate with a run-time error of
250 (if lsInit has been called directly) or 251 (if lsInit has
been called while attempting to allocate space on the ring
buffer.
See Also:
lsDispose
ShLngStr 9-14
____________________________
lsIOFF
Declarations:
procedure lsIoff;
Purpose:
Turns I/O checking off during execution of lsReadLn and
lsWriteLn.
Examples:
lsIoff;
lsReadLn(MyFile, MyLS);
if lsIoResult <> 0 then {Do something}
lsIon;
Comments:
lsIoff, lsIon, and lsIoResult MUST be used for LongString
I/O operations in place of $I-, $I+, and IoResult.
Emulates at execution time the action of the $I- compiler
directive, but only for LongString I/O. The default state is
"on".
If I/O checking is off lsIoResult MUST be called after each
call to lsReadLn or lsWriteLn. If I/O checking is on, and if an
I/O error occurs, the program will terminate with a run-time
error. This action duplicates the action of the IoResult function
for normal I/O.
See Also:
lsIon lsIoResult
ShLngStr 9-15
____________________________
lsION
Declarations:
procedure lsIon;
Purpose:
Turns I/O checking on during execution of lsReadLn and
lsWriteLn.
Examples:
lsIoff;
lsReadLn(MyFile, MyLS);
if lsIoResult <> 0 then {Do something}
lsIon;
Comments:
lsIoff, lsIon, and lsIoResult MUST be used for LongString
I/O operations in place of $I-, $I+, and IoResult.
Emulates at execution time the action of the $I+ compiler
directive, but only for LongString I/O. The default state is
"on".
If I/O checking is off lsIoResult MUST be called after each
call to lsReadLn or lsWriteLn. If I/O checking is on, and if an
I/O error occurs, the program will terminate with a run-time
error. This action duplicates the action of the IoResult function
for normal I/O.
See Also:
lsIoff lsIoResult
ShLngStr 9-16
____________________________
lsIORESULT
Declarations:
function lsIoResult: word;
Purpose:
Returns the IoResult of the last lsReadLn or lsWriteLn
performed, and clears the internal variable used to store the
value.
Examples:
lsIoff;
lsReadLn(MyFile, MyLS);
if lsIoResult <> 0 then {Do something}
lsIon;
Comments:
lsIoff, lsIon, and lsIoResult MUST be used for LongString
I/O operations in place of $I-, $I+, and IoResult.
If I/O checking is off lsIoResult MUST be called after each
call to lsReadLn or lsWriteLn. If I/O checking is on, and if an
I/O error occurs, the program will terminate with a run-time
error. This action duplicates the action of the IoResult function
for normal I/O.
See Also:
lsIoff lsIon
ShLngStr 9-17
____________________________
lsINSERT
Declarations:
procedure lsInsert
(A, Obj: LongString; Start: word; B: LongString);
function lsInsertF
(A, Obj: LongString; Start: word): LongString;
procedure lsInsertStr
(A: LongString; Obj: string; Start: word;
B: LongString);
function lsInsertStrF
(A: LongString; Obj: string; Start: word): LongString;
Purpose:
Insert Obj into A at position Start returning a new
LongString.
Examples:
If A contains "abcdef"
and Obj contains "ABC"
then lsInsert(A, Obj, 4, B);
results in B containing "abcABCdef"
Comments:
If Start > lsLength(A), no action is taken.
See Also:
lsDelete
ShLngStr 9-18
____________________________
lsLEFTPAD
Declarations:
procedure lsLeftPad
(A: LongString; Len: word; B: LongString);
function lsLeftPadF
(A: LongString; Len: word): LongString;
Purpose:
Left-pad the LongString in A to length Len with blanks,
returning a new LongString.
Examples:
If A contains "abc"
then lsLeftPad(A, 5, B);
results in B containing " abc"
Comments:
If Len < lsLength(A), A is returned truncated without
padding.
See Also:
lsLeftPadCh lsPad lsPadCh
____________________________
lsLEFTPADCH
Declarations:
procedure lsLeftPadCh
(A: LongString; Ch: Char; Len: word; B: LongString);
function lsLeftPadChF
(A: LongString; Ch: Char; Len: word): LongString;
Purpose:
Left-pad the LongString in A to length Len with Ch,
returning a new LongString.
Examples:
If A contains "abc"
then lsLeftPad(A, '+', 5, B);
results in B containing "++abc"
Comments:
See Also:
lsLeftPad lsPad lsPadCh
ShLngStr 9-19
____________________________
lsLENGTH
Declarations:
function lsLength
(A: LongString): word;
Purpose:
Return the length of a LongString. A must have been
initialized.
Examples:
If A contains "Cogito, ergo sum."
then lsLength(A)
returns 17
Comments:
See Also:
____________________________
lsLOCASE
Declarations:
procedure lsLocase
(A, B: LongString);
function lsLocaseF
(A: LongString): LongString;
Purpose:
Locase the LongString in A, returning a new LongString.
Examples:
If A contains "ABCdefGHIjkl"
then lsLocase(A, B);
results in B containing "abcdefghijkl"
Comments:
See Also:
lsUpcase
ShLngStr 9-20
____________________________
lsLONGSTRING2STR
Declarations:
function lsLongString2Str
(A: LongString): string;
Purpose:
Convert a LongString to a Turbo string.
Examples:
If A (LongString) contains "abcdef"
then lsLongString2Str(A)
returns 'abcdef' (string)
Comments:
If lsLength(A) > 255, the returned string will be truncated
to length 255.
See Also:
lsStr2LongString
____________________________
lsPAD
Declarations:
procedure lsPad
(A: LongString; Len: word; B: LongString);
function lsPadF
(A: LongString; Len: word): LongString;
Purpose:
Right-pad the LongString in A to length Len with blanks,
returning a new LongString.
Examples:
If A contains "abc"
then lsPad(A, 5, B);
results in B containing "abc "
but if lsInit(C, 5) = true
then lsPad(A, 8, C);
also results in C containing "abc "
Comments:
See Also:
lsPadCh lsLeftPad lsLeftPadCh
ShLngStr 9-21
____________________________
lsPADCH
Declarations:
procedure lsPadCh
(A: LongString; Ch: Char; Len: word; B: LongString);
function lsPadChF
(A: LongString; Ch: Char; Len: word): LongString;
Purpose:
Right-pad the LongString in A to length Len with Ch,
returning a new LongString.
Examples:
If A contains "abc"
then lsPadCh(A, '+', 5, B);
results in B containing "abc++"
but if lsInit(C, 5) = true
then lsPadCh(A, '+', 8, C);
also results in C containing "abc++"
Comments:
See Also:
lsPad lsLeftPad lsLeftPadCh
ShLngStr 9-22
____________________________
lsPOS
Declarations:
function lsPos
(Obj, A: LongString): word;
function lsPosStr
(Obj: string; A: LongString): word;
function lsPosUC
(Obj, A: LongString): word;
function lsPosStrUC
(Obj: string; A: LongString): word;
Purpose:
Return the position of Obj in A, returning NotFound if not
found.
Examples:
If A contains "abcdeabcdeabcde"
and Obj contains "BCD"
then lsPos(A, Obj)
returns NotFound ( = 0 )
but lsPosUC(A, Obj)
returns 2
Comments:
See Also:
____________________________
lsPOSSET
Declaration:
function lsPosSet(A : CharSet; S : LongString) : word;
Purpose:
Returns the position of the first occurrence of any member
of A in S.
Comments:
This function is primarily intended for internal use.
Examples:
If S = 'X1Y2C3Z4B'
and A = ['A','B','C']
then lsPosSet(A, S) will return 5.
See also:
ShLngStr 9-23
____________________________
lsREADLN
Declarations:
procedure lsReadLn
(var F: Text; A: LongString);
Purpose:
Read a LongString from a text file.
Examples:
lsReadLn(MyFile, A);
Comments:
If the "declared" length of A (set by lsInit) is less than
the actual length of the line in the text file, the incoming
string will be truncated to the "declared" length of A and the
file will be positioned at the beginning of the next line (the
exact analog of a normal Turbo PASCAL string ReadLn).
If I/O checking is off lsIoResult MUST be called after each
call to lsReadLn or lsWriteLn. If I/O checking is on, and if an
I/O error occurs, the program will terminate with a run-time
error. This action duplicates the action of the IoResult function
for normal I/O.
See Also:
lsIoff lsIon lsIoResult lsWriteLn
ShLngStr 9-24
____________________________
lsREPALL
Declarations:
procedure lsRepAll
(A, Obj, Obj1, B: LongString);
function lsRepAllF
(A, Obj, Obj1: LongString): LongString;
procedure lsRepAllStr
(A: LongString; Obj, Obj1: string; B: LongString);
function lsRepAllStrF
(A: LongString; Obj, Obj1: string): LongString;
procedure lsRepAllStrUC
(A: LongString; Obj, Obj1: string; B: LongString);
function lsRepAllStrUCF
(A: LongString; Obj, Obj1: string): LongString;
procedure lsRepAllUC
(A, Obj, Obj1, B: LongString);
function lsRepAllUCF
(A, Obj, Obj1: LongString): LongString;
Purpose:
Replaces all occurrences of Obj in A with Obj1.
Examples:
If A contains 'aabcbcabcd'
and Obj contains 'abc'
and Obj1 contains '12345'
then lsRepAll(A, Obj, Obj1, B);
results in B containing 'a12345bc12345d'
Comments:
Should the replacement of Obj by Obj1 in A result in a new
occurrence of Obj in A, the new occurrence will not be replaced.
To do so, except under rather unusual conditions, could result in
a non-terminating condition.
See Also:
lsDelAll
ShLngStr 9-25
____________________________
lsSIZEOF
Declarations:
function lsSizeOf
(A: LongString): word;
Purpose:
Returns the total heap space required for A, including the
two control words. A must have been initialized.
Examples:
See below.
Comments:
lsSizeOf MUST be used to determine the effective size of a
LongString. Any attempt to use SizeOf(A) will return a value of
4; any attempt to use SizeOf(A^) will return a value of 5.
Neither is particularly informative!
Remember that, just as
SizeOf(StringVariable)
returns a value one greater than the declared length of
StringVariable, so
lsSizeOf(LongStringVariable)
will return a value four greater than the "declared" length of
LongStringVariable.
If A has not been initialized, the results are
unpredictable.
See Also:
lsLength
ShLngStr 9-26
____________________________
lsSTR2LONGSTRING
Declarations:
procedure lsStr2LongString
(S: string; A: LongString);
function lsStr2LongStringF
(S: string): LongString;
Purpose:
Convert a Turbo string into a LongString.
Examples:
If S (string) contains "abcdef"
then lsStr2LongString(S, A);
results in A (LongString) containing "abcdef"
Comments:
See Also:
lsLongString2Str
____________________________
lsTRANSFER
Declarations:
procedure lsTransfer
(A, B: LongString);
Purpose:
Transfers the contents of A into B.
Examples:
B^ := A^;
INCORRECT!! This construct will give unpredictable but guar-
anteed incorrect results.
lsTransfer(A, B);
Correct. ALWAYS use lsTransfer to move the contents of one
LongString into another.
Comments:
See Also:
ShLngStr 9-27
____________________________
lsTRIM
Declarations:
procedure lsTrim
(A, B: LongString);
function lsTrimF
(A: LongString): LongString;
Purpose:
Return a LongString with leading and trailing white space
removed.
Examples:
If A contains " Cogito, ergo sum. "
then lsTrim(A, B);
results in B containing "Cogito, ergo sum."
Comments:
"White space" is any sequence of characters in the range
#0..#32.
See Also:
lsTrimLead lsTrimTrail
lsTrimLeadSet lsTrimSet lsTrimTrailSet
____________________________
lsTRIMLEAD
Declarations:
procedure lsTrimLead
(A, B: LongString);
function lsTrimLeadF
(A: LongString): LongString;
Purpose:
Return a LongString with leading white space removed.
Examples:
If A contains " Cogito, ergo sum. "
then lsTrimLead(A, B);
results in B containing "Cogito, ergo sum. "
Comments:
"White space" is any sequence of characters in the range
#0..#32.
See Also:
lsTrim lsTrimTrail
lsTrimLeadSet lsTrimSet lsTrimTrailSet
ShLngStr 9-28
____________________________
lsTRIMTRAIL
Declarations:
procedure lsTrimTrail
(A, B: LongString);
function lsTrimTrailF
(A: LongString): LongString;
Purpose:
Return a LongString with trailing white space removed.
Examples:
If A contains " Cogito, ergo sum. "
then lsTrimTrail(A, B);
results in B containing " Cogito, ergo sum."
Comments:
"White space" is any sequence of characters in the range
#0..#32.
See Also:
lsTrim lsTrimLead
lsTrimLeadSet lsTrimSet lsTrimTrailSet
____________________________
lsTRIMLEADSET
Declaration:
procedure lsTrimLeadSet
(A : LongString; CS : CharSet; B : LongString);
function lsTrimLeadSetF
(A : LongString; CS : CharSet) : LongString;
Purpose:
Returns a LongString with leading characters in CS stripped.
Examples:
See the file TESTLSTR.PAS
Comments:
CS contains an arbitrary set of characters.
See also:
lsTrimSet lsTrimTrailSet
lsTrim lsTrimLead lsTrimTrail
ShLngStr 9-29
____________________________
lsTRIMSET
Declaration:
procedure lsTrimSet
(A : LongString; CS : CharSet; B : LongString);
function lsTrimSetF
(A : LongString; CS : CharSet) : LongString;
Purpose:
Returns a LongString with leading and trailing characters in
CS stripped.
Examples:
See the file TESTLSTR.PAS
Comments:
CS contains an arbitrary set of characters.
See also:
lsTrimLeadSet lsTrimTrailSet
lsTrim lsTrimLead lsTrimTrail
____________________________
lsTRIMTRAILSET
Declaration:
procedure lsTrimTrailSet
(A : LongString; CS : CharSet; B : LongString);
function lsTrimTrailSetF
(A : LongString; CS : CharSet) : LongString;
Purpose:
Returns a LongString with trailing characters in CS
stripped.
Examples:
See the file TESTLSTR.PAS
Comments:
CS contains an arbitrary set of characters.
See also:
lsTrimLeadSet lsTrimSet
lsTrim lsTrimLead lsTrimTrail
ShLngStr 9-30
____________________________
lsUPCASE
Declarations:
procedure lsUpcase
(A, B: LongString);
function lsUpcaseF
(A: LongString): LongString;
Purpose:
Upcase the LongString in A, returning a new LongString.
Examples:
If A contains "ABCdefGHIjkl"
then lsUpcase(A, B);
results in B containing "ABCDEFGHIJKL"
Comments:
See Also:
lsLocase
____________________________
lsWRITELN
Declarations:
procedure lsWriteLn
(var F: Text; A: LongString);
Purpose:
Write a LongString to a text file.
Examples:
lsWriteLn(MyFile, A);
Comments:
If I/O checking is off lsIoResult MUST be called after each
call to lsReadLn or lsWriteLn. If I/O checking is on, and if an
I/O error occurs, the program will terminate with a run-time
error. This action duplicates the action of the IoResult function
for normal I/O.
See Also:
lsIoff lsIon lsIoResult lsReadLn
ShLngStr 9-31
06/15/92 09:46am
This page has been deliberately left
blank, except for this message.
ShLngStr 9-32
ShUtilPk
A Utility Unit
INTRODUCTION
ShUtilPk provides a number of miscellaneous utility routines
which do not fit naturally into any of the other units of the
SkyHawk collection.
INTERFACED ELEMENTS
Types
=====
DelimSetType = Set of Char;
CharSet = Set of Char;
Constants
=========
DelimSet : DelimSetType = [#0..#32];
The typed constant used by the GetNext routines to determine
the end of a substring to be returned. It may be freely changed
during program execution.
Variables
=========
Two variables are interfaced, containing the video mode and
video attribute of the system at the time the containing program
was invoked. NEVER MODIFY THESE VARIABLES!
StartingMode : Integer;
{Initial video mode of the system (Mono, CO80, BW40, ...)}
StartingAttr : Byte;
{Initial video attribute of the system}
ShUtilPk 10-1
Routines
========
____________________________
BETWS
Declaration:
function BetwS(Lower, Item, Upper : LongInt) : boolean;
Purpose:
Performs a SIGNED test of the condition that
Lower <= Item <= Upper
returning TRUE if and only if the condition is met.
Comments:
Lower, Item, and Upper can be any combination of 1, 2, and
4-byte entities.
Note that
BetwU($EA, $EA, $FA) = true
whereas
BetwS($EA, $EA, $FA) = false
Examples:
See TESTBETW.PAS
See also:
BetwU
ShUtilPk 10-2
____________________________
BETWU
Declaration:
function BetwU(Lower, Item, Upper : LongInt) : boolean;
Purpose:
Performs an UNSIGNED test of the condition that
Lower <= Item <= Upper
returning TRUE if and only if the condition is met.
Comments:
Lower, Item, and Upper can be any combination of 1, 2, and
4-byte entities.
Note that
BetwU($EA, $EA, $FA) = true
whereas
BetwS($EA, $EA, $FA) = false
Examples:
See TESTBETW.PAS
See also:
BetwS
____________________________
DELALL
Declaration:
procedure DelAll(S1, DS : String; S2);
function DelAllF(S1, DS : string) : string;
Purpose:
In string S1 delete all occurrences of DS.
Comments:
Examples:
See the file TESTUTIL.PAS
See also:
RepAll
ShUtilPk 10-3
____________________________
GETNEXT
Declaration:
procedure GetNext(var S1, S2 : String);
function GetNextF(var S1 : String) : String;
Purpose:
Returns the next leading substring of S1 which is delimited
by a member of DelimSet.
Comments:
S1 is returned with the sub-string stripped off, but not
trimmed. S2 or the function value is trimmed.
If S1 is empty on entry, both S1 and S2 (or the function
value) will be empty on return.
Examples:
See the file TESTUTIL.PAS
See also:
ShUtilPk 10-4
____________________________
HEX
Declaration:
function HEX(A : LongInt) : String;
Purpose:
Converts any INTEGER-type variable into a string
correspnoding to the hex value.
Comments:
The parameter A may be of any Integer type (ShortInt, Byte,
Integer, Word, or LongInt
HEX will return either a 2, 4, or 8 character string,
depending on whether the actual value of the parameter (rather
than its type) is representable by a
1 byte value (ShortInt, Byte)
2 byte value (Integer, Word)
4 byte value (LongInt)
Note that a negative value will always be returned as an 8
character string.
Examples:
See the file TESTUTIL.PAS
See also:
____________________________
HIWORD
Declaration:
function HiWord(LI : LongInt) : Word;
Purpose:
Returns the high order word of a LongInt.
Comments:
This function is the analog of the system function HI, per-
forming the analogous operation on a LongInt to that performed by
HI on an INTEGER or WORD.
Examples:
See the file TESTUTIL.PAS
See also:
LoWord
ShUtilPk 10-5
____________________________
LI
Declaration:
function LI(Ilo, Ihi : Word) : LongInt;
Purpose:
Converts two Word variables to a LongInt
Comments:
Examples:
See the file TESTUTIL.PAS
See also:
____________________________
LOWORD
Declaration:
function LoWord(LI : LongInt) : Word;
Purpose:
Returns the low order word of a LongInt.
Comments:
This function is the analog of the system function LO, per-
forming the analogous operation on a LongInt to that performed by
LO on an INTEGER or WORD.
Examples:
See the file TESTUTIL.PAS
See also:
HiWord
ShUtilPk 10-6
____________________________
PMOD
Declaration:
function Pmod(X, Modulus : LongInt) : LongInt;
Purpose:
Returns the remainder of X on division by MODULUS as a
positive number, regardless of the sign of X.
Comments:
Recall that, e.g., -1 is congruent to (modulus-1). Thus, for
example, Pmod(-2, 7) will return 5 as the function value.
Examples:
(-2 mod 5) = -2
Pmod(-2, 5) = 3
See the file TESTUTIL.PAS
See also:
____________________________
POSSET
Declaration:
function PosSet(A : CharSet; S : string) : byte;
Purpose:
Returns the position of the first occurrence of any member
of A in S.
Comments:
This function is intended primarily for internal use by
ShUtilPk and ShCmdLin.
Examples:
If S = 'X1Y2C3Z4B'
and A = ['A','B','C']
then PosSet(A, S) will return 5.
See the file TESTUTIL.PAS
See also:
ShUtilPk 10-7
____________________________
REPALL
Declaration:
procedure RepAll(S1, FS, SS : String; var S2 : string);
function RepAllF(S1, FS, SS : string) : string;
Purpose:
In string S1 replace all occurrences of FS with SS
Comments:
Examples:
See the file TESTUTIL.PAS
See also:
DelAll
____________________________
SEARCHENVIRONMENT
Declaration:
function SearchEnvironment(Code : String) : String;
Purpose:
Searches the environment space for "CODE" and returns the
corresponding string.
Comments:
If the CODE string has not been set with a SET statement,
the function will return an empty string.
Examples:
If the DOS command
SET GORP=FooBaz
has been executed, then
SearchEnvironment('GORP')
will return
'FooBaz'
See also:
ShUtilPk 10-8
____________________________
STARSTRING
Declaration:
function StarString(Pattern, Target : String) : Boolean;
Purpose:
This function performs a generalization of the wildcard
string matching usually performed by DOS.
Comments:
The mask is presented in Pattern, and the string to be
scanned is presented in Target. The function will return TRUE or
FALSE as the target does or does not match the mask.
A '*' wild card can be placed anywhere within the mask, and
will represent its usual 'zero or more of any characters'. Scan-
ning will not be terminated at that point, however, but will con-
tinue. Thus, '*B*EFG' will match 'ABCDEFG', but '*B*EGF' will
not. Similarly, '*ABC*' will match, but '*ABC' will not.
A '?' wild card can also be placed anywhere within the mask,
and will also represent its usual 'one occurrance of any char-
acter'.
Examples:
StarString('*B*EFG', 'ABCDEFG')
returns TRUE.
StarString('*B*EGF', 'ABCDEFG')
returns FALSE
but would return TRUE using the DOS algorithm.
See the file TESTUTIL.PAS
See also:
ShUtilPk 10-9
____________________________
UNIQUEFILENAME
Declaration:
function UniqueFileName
(Path : String; AddExt : Boolean) : string;
Purpose:
Returns a file name which will be unique in the directory
specified by PATH.
Comments:
On return, the file name will be appended to PATH to give a
fully qualified path.
If AddExt is TRUE, an extension of .$$$ will be appended,
else only the file name will be returned. In either case, the
returned entity is guaranteed to be unique.
Examples:
See the file TESTUTIL.PAS
See also:
____________________________
WHOAMI
Declaration:
function WhoAmI : String;
Purpose:
Returns the fully qualified path to the currently executing
file.
Comments:
Can be used with DOS 3.x or above, ONLY.
Examples:
See the file TESTUTIL.PAS
See also:
ShUtilPk 10-10
06/15/92 09:46am
Index
80x87 errors....... 7.2 CompPresVal........ 7.4
Count.............. 8.3
A CpPwrR............. 3.8
AnnType............ 7.1 CpPwrRF............ 3.8
AnnuityAmount...... 7.2 CrcCalc............ 4.2
AnnuityPresVal..... 7.3 CrcCopy............ 4.3
CSub............... 3.9
B CSubF.............. 3.9
BetwS............. 10.2 Current............ 8.3
BetwU............. 10.2
D
C Data............... 8.2
C2P................ 3.3 DataRecSize........ 8.3
C2PF............... 3.3 Day................ 5.2
CAbs............... 3.4 DayStr............. 5.2
CAbsF.............. 3.4 DelAll............ 10.3
CAdd............... 3.4 DelAllF........... 10.3
CAddF.............. 3.4 DelimSet.......... 10.1
CConj.............. 3.5 DelimSetType...... 10.1
CConjF............. 3.5 dlAppend........... 8.4
CDiv............... 3.5 dlCount............ 8.4
CDivF.............. 3.5 dLength............ 9.3
CharSet. 2.2, 9.3, 10.1 dlFree............. 8.5
CheckOff........... 6.2 dlGetCurrent....... 8.6
CheckOn............ 6.2 dlGetFirst......... 8.6
ClClose............ 2.3 dlGetLast.......... 8.7
ClInit............. 2.3 dlGetNext.......... 8.7
ClParse............ 2.4 dlGetPrev.......... 8.8
Cmp2Str............ 3.6 dlLessFunc......... 8.3
CmplxError......... 3.6 dlList............. 8.3
CmpP2Str........... 3.7 dlListInit......... 8.9
CmpP2StrD.......... 3.7 dlNode............. 8.2
CMul............... 3.8 dlNodePtr.......... 8.2
CMulF.............. 3.8 dlPop............. 8.10
Color Constants... 1.1, dlPush............ 8.11
1.3 dlPut............. 8.12
ColorName.......... 1.5 dlPutPrev......... 8.12
CompAmount......... 7.3 dlPutSorted....... 8.13
Complex............ 3.3 dlSpaceUsed....... 8.14
ComplexBaseType.... 3.3 DoW................ 5.3
ComplexElement..... 3.3 DP................. 7.2
index-i
F IntVal............. 2.2
fin87errCode....... 7.4 IW................. 7.2
fin87error......... 7.2
fin80x87error...... 7.1 J
finDenormalizedOperand. JDate2Greg......... 5.5
7.2 JDN2ANSI........... 5.5
finDivideByZero.... 7.2 JDN2Greg........... 5.6
finErrCheckOff..... 7.5 JDN2Str............ 5.7
finErrCheckOn...... 7.5
finErrCode......... 7.6 L
finErrMsg.......... 7.6 Length............. 9.3
finError........... 7.2 LI................ 10.6
finErrParamTooSmall.... LongString......... 9.3
7.1 LongStringType..... 9.3
finIllegalNumPeriods... LoWord............ 10.6
7.1 lsCenter........... 9.5
finIllegalPresentValue. lsCenterCh......... 9.5
7.1 lsCenterChF........ 9.5
finIndeterminateForm... lsCenterF.......... 9.5
7.1 lsCharStr.......... 9.6
finIntOutOfRange... 7.1 lsCharStrF......... 9.6
finInvalidOperation.... lsComp............. 9.7
7.2 lsCompType......... 9.3
finNoConvergence... 7.1 lsConcat........... 9.7
finOK.............. 7.1 lsConcatF.......... 9.7
finOverflow........ 7.2 lsConcatLs2Str..... 9.7
finUnderflow....... 7.2 lsConcatLs2StrF.... 9.7
finUnknownAnnuityType.. lsConcatStr2Ls..... 9.7
7.1 lsConcatStr2LsF.... 9.7
FW................. 7.2 lsCopy............. 9.8
lsCopyF............ 9.8
G lsCount............ 9.9
GetNext........... 10.4 lsCountStr......... 9.9
GetNextF.......... 10.4 lsCountStrUC....... 9.9
GetSwitch.......... 2.6 lsCountUC.......... 9.9
Greg2ANSI.......... 5.3 lsData............. 9.3
Greg2JDate......... 5.4 lsDelAll.......... 9.10
Greg2JDN........... 5.4 lsDelAllF......... 9.10
Greg2Str........... 5.6 lsDelAllStr....... 9.10
GregType........... 5.2 lsDelAllStrF...... 9.10
lsDelAllStrUC..... 9.10
H lsDelAllStrUCF.... 9.10
H.................. 5.2 lsDelAllUC........ 9.10
HaltMsg............ 6.3 lsDelAllUCF....... 9.11
Head............... 8.3 lsDelete.......... 9.12
HEX............... 10.4 lsDeleteF......... 9.12
HiWord............ 10.5 lsDelimSet......... 9.3
lsDelimSetType..... 9.3
I lsDispose......... 9.12
IfromPresVal....... 7.7 lsGetNext......... 9.13
Im................. 3.3 lsGetNextF........ 9.13
index-ii
lsGetNextStr...... 9.13 lsTrimTrailSetF... 9.30
lsGetNextStrF..... 9.13 lsUpcase.......... 9.31
lsInit............ 9.13 lsUpcaseF......... 9.31
lsInsert.......... 9.17 lsWriteLn......... 9.31
lsInsertF......... 9.17
lsInsertStr....... 9.17 M
lsInsertStrF...... 9.17 M.................. 5.2
lsIoff............ 9.14 MaxLongString...... 9.4
lsIon............. 9.15 Month.............. 5.2
lsIoResult........ 9.16 MonthStr........... 5.2
lsLeftPad......... 9.18
lsLeftPadCh....... 9.19 N
lsLeftPadChF...... 9.19 Name............... 2.2
lsLeftPadF........ 9.18 Next............... 8.2
lsLength.......... 9.20 NotFound........... 9.4
lsLocase.......... 9.20 Now................ 5.7
lsLocaseF......... 9.20 Now2Time........... 5.7
lsLongString2Str.. 9.21 NowStr............. 5.8
lsPad............. 9.21 NumPay............. 7.7
lsPadCh........... 9.22
lsPadChF.......... 9.22 O
lsPadF............ 9.21 Orientation........ 1.3
lsPos............. 9.22
lsPosSet.......... 9.23 P
lsPosStr.......... 9.22 P2C................ 3.9
lsPosStrUC........ 9.22 P2CF............... 3.9
lsPosUC........... 9.22 Pmod.............. 10.7
lsReadLn.......... 9.24 PopSwitch.......... 2.6
lsRepAll.......... 9.24 PosSet............ 10.7
lsRepAllF......... 9.24 Prev............... 8.2
lsRepAllStr....... 9.24
lsRepAllStrF...... 9.24 R
lsRepAllStrUC..... 9.24 Re................. 3.3
lsRepAllStrUCF.... 9.24 ReadSwCh........... 2.7
lsRepAllUC........ 9.24 RealVal............ 2.2
lsRepAllUCF....... 9.24 RepAll............ 10.8
lsSizeOf.......... 9.25 RepAllF........... 10.8
lsStr2LongString.. 9.26 RingSize........... 9.3
lsStr2LongStringF. 9.26 RunErrorMsg........ 6.3
lsTransfer........ 9.27 RxC............... 3.10
lsTrim............ 9.28 RxCF.............. 3.10
lsTrimF........... 9.28
lsTrimLead........ 9.28 S
lsTrimLeadF....... 9.28 S.................. 5.2
lsTrimLeadSet..... 9.29 SearchEnvironment. 10.8
lsTrimLeadSetF.... 9.29 SelectColors....... 1.3
lsTrimSet......... 9.30 SetSwCh............ 2.8
lsTrimSetF........ 9.30 slAppend........... 8.4
lsTrimTrail....... 9.29 slCount............ 8.4
lsTrimTrailF...... 9.29 slFree............. 8.5
lsTrimTrailSet.... 9.30 slGetCurrent....... 8.6
index-iii
slGetFirst......... 8.6 Time2SSM........... 5.9
slGetLast.......... 8.7 Time2TimeStr...... 5.10
slGetNext.......... 8.7 TimeType........... 5.2
slList............. 8.3 Today............. 5.10
slListInit......... 8.9 Today2ANSI........ 5.11
slNode............. 8.2 Today2Greg........ 5.11
slNodePtr.......... 8.2 TodayStr.......... 5.12
slPop............. 8.10
slPush............ 8.11 U
slPut............. 8.12 UniqueFileName.... 10.9
slSpaceUsed....... 8.14
SSM2Time........... 5.8 V
SSM2TimeStr........ 5.9 ValueType.......... 2.2
StarString........ 10.9 VtInt.............. 2.2
StartingAttr...... 10.1 VtReal............. 2.2
StartingMode...... 10.1 VtStr.............. 2.2
StrVal............. 2.2
SwRec.............. 2.2 W
SwVal.............. 2.2 WhoAmI........... 10.10
T Y
Tail............... 8.3 Year............... 5.2
index-iv